]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
fix vpack support to actually work; use a pack_s structure for vpack items
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 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)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 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"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 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)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 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"};
70 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"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 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"};
73 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"};
74 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"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 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."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 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."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 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"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
116 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
117 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
118
119 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)"};
120 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
121 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
122 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
123 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
124 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)"};
125 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)"};
126 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)"};
127 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)"};
128
129 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)"};
130 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
131 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"};
132 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
133 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
134
135 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
136 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
137 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
138 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
139
140 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
141 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
142 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
143 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
144 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
145 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
146 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
147
148 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
149 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
150 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
151 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)"};
152
153 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"};
154
155 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"};
156
157 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
158
159 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
160 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
161 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"};
162 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
163 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
164 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
165 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
166
167 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "1", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
168
169 extern cvar_t v_glslgamma;
170
171 extern qboolean v_flipped_state;
172
173 static struct r_bloomstate_s
174 {
175         qboolean enabled;
176         qboolean hdr;
177
178         int bloomwidth, bloomheight;
179
180         int screentexturewidth, screentextureheight;
181         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
182
183         int bloomtexturewidth, bloomtextureheight;
184         rtexture_t *texture_bloom;
185
186         // arrays for rendering the screen passes
187         float screentexcoord2f[8];
188         float bloomtexcoord2f[8];
189         float offsettexcoord2f[8];
190
191         r_viewport_t viewport;
192 }
193 r_bloomstate;
194
195 r_waterstate_t r_waterstate;
196
197 /// shadow volume bsp struct with automatically growing nodes buffer
198 svbsp_t r_svbsp;
199
200 rtexture_t *r_texture_blanknormalmap;
201 rtexture_t *r_texture_white;
202 rtexture_t *r_texture_grey128;
203 rtexture_t *r_texture_black;
204 rtexture_t *r_texture_notexture;
205 rtexture_t *r_texture_whitecube;
206 rtexture_t *r_texture_normalizationcube;
207 rtexture_t *r_texture_fogattenuation;
208 rtexture_t *r_texture_gammaramps;
209 unsigned int r_texture_gammaramps_serial;
210 //rtexture_t *r_texture_fogintensity;
211
212 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
213 unsigned int r_numqueries;
214 unsigned int r_maxqueries;
215
216 typedef struct r_qwskincache_s
217 {
218         char name[MAX_QPATH];
219         skinframe_t *skinframe;
220 }
221 r_qwskincache_t;
222
223 static r_qwskincache_t *r_qwskincache;
224 static int r_qwskincache_size;
225
226 /// vertex coordinates for a quad that covers the screen exactly
227 const float r_screenvertex3f[12] =
228 {
229         0, 0, 0,
230         1, 0, 0,
231         1, 1, 0,
232         0, 1, 0
233 };
234
235 extern void R_DrawModelShadows(void);
236
237 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
238 {
239         int i;
240         for (i = 0;i < verts;i++)
241         {
242                 out[0] = in[0] * r;
243                 out[1] = in[1] * g;
244                 out[2] = in[2] * b;
245                 out[3] = in[3];
246                 in += 4;
247                 out += 4;
248         }
249 }
250
251 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
252 {
253         int i;
254         for (i = 0;i < verts;i++)
255         {
256                 out[0] = r;
257                 out[1] = g;
258                 out[2] = b;
259                 out[3] = a;
260                 out += 4;
261         }
262 }
263
264 // FIXME: move this to client?
265 void FOG_clear(void)
266 {
267         if (gamemode == GAME_NEHAHRA)
268         {
269                 Cvar_Set("gl_fogenable", "0");
270                 Cvar_Set("gl_fogdensity", "0.2");
271                 Cvar_Set("gl_fogred", "0.3");
272                 Cvar_Set("gl_foggreen", "0.3");
273                 Cvar_Set("gl_fogblue", "0.3");
274         }
275         r_refdef.fog_density = 0;
276         r_refdef.fog_red = 0;
277         r_refdef.fog_green = 0;
278         r_refdef.fog_blue = 0;
279         r_refdef.fog_alpha = 1;
280         r_refdef.fog_start = 0;
281         r_refdef.fog_end = 16384;
282         r_refdef.fog_height = 1<<30;
283         r_refdef.fog_fadedepth = 128;
284 }
285
286 static void R_BuildBlankTextures(void)
287 {
288         unsigned char data[4];
289         data[2] = 128; // normal X
290         data[1] = 128; // normal Y
291         data[0] = 255; // normal Z
292         data[3] = 128; // height
293         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
294         data[0] = 255;
295         data[1] = 255;
296         data[2] = 255;
297         data[3] = 255;
298         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
299         data[0] = 128;
300         data[1] = 128;
301         data[2] = 128;
302         data[3] = 255;
303         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
304         data[0] = 0;
305         data[1] = 0;
306         data[2] = 0;
307         data[3] = 255;
308         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
309 }
310
311 static void R_BuildNoTexture(void)
312 {
313         int x, y;
314         unsigned char pix[16][16][4];
315         // this makes a light grey/dark grey checkerboard texture
316         for (y = 0;y < 16;y++)
317         {
318                 for (x = 0;x < 16;x++)
319                 {
320                         if ((y < 8) ^ (x < 8))
321                         {
322                                 pix[y][x][0] = 128;
323                                 pix[y][x][1] = 128;
324                                 pix[y][x][2] = 128;
325                                 pix[y][x][3] = 255;
326                         }
327                         else
328                         {
329                                 pix[y][x][0] = 64;
330                                 pix[y][x][1] = 64;
331                                 pix[y][x][2] = 64;
332                                 pix[y][x][3] = 255;
333                         }
334                 }
335         }
336         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
337 }
338
339 static void R_BuildWhiteCube(void)
340 {
341         unsigned char data[6*1*1*4];
342         memset(data, 255, sizeof(data));
343         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
344 }
345
346 static void R_BuildNormalizationCube(void)
347 {
348         int x, y, side;
349         vec3_t v;
350         vec_t s, t, intensity;
351 #define NORMSIZE 64
352         unsigned char *data;
353         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
354         for (side = 0;side < 6;side++)
355         {
356                 for (y = 0;y < NORMSIZE;y++)
357                 {
358                         for (x = 0;x < NORMSIZE;x++)
359                         {
360                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
361                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
362                                 switch(side)
363                                 {
364                                 default:
365                                 case 0:
366                                         v[0] = 1;
367                                         v[1] = -t;
368                                         v[2] = -s;
369                                         break;
370                                 case 1:
371                                         v[0] = -1;
372                                         v[1] = -t;
373                                         v[2] = s;
374                                         break;
375                                 case 2:
376                                         v[0] = s;
377                                         v[1] = 1;
378                                         v[2] = t;
379                                         break;
380                                 case 3:
381                                         v[0] = s;
382                                         v[1] = -1;
383                                         v[2] = -t;
384                                         break;
385                                 case 4:
386                                         v[0] = s;
387                                         v[1] = -t;
388                                         v[2] = 1;
389                                         break;
390                                 case 5:
391                                         v[0] = -s;
392                                         v[1] = -t;
393                                         v[2] = -1;
394                                         break;
395                                 }
396                                 intensity = 127.0f / sqrt(DotProduct(v, v));
397                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
398                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
399                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
400                                 data[((side*64+y)*64+x)*4+3] = 255;
401                         }
402                 }
403         }
404         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
405         Mem_Free(data);
406 }
407
408 static void R_BuildFogTexture(void)
409 {
410         int x, b;
411 #define FOGWIDTH 256
412         unsigned char data1[FOGWIDTH][4];
413         //unsigned char data2[FOGWIDTH][4];
414         double d, r, alpha;
415
416         r_refdef.fogmasktable_start = r_refdef.fog_start;
417         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
418         r_refdef.fogmasktable_range = r_refdef.fogrange;
419         r_refdef.fogmasktable_density = r_refdef.fog_density;
420
421         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
422         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
423         {
424                 d = (x * r - r_refdef.fogmasktable_start);
425                 if(developer_extra.integer)
426                         Con_DPrintf("%f ", d);
427                 d = max(0, d);
428                 if (r_fog_exp2.integer)
429                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
430                 else
431                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
432                 if(developer_extra.integer)
433                         Con_DPrintf(" : %f ", alpha);
434                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
435                 if(developer_extra.integer)
436                         Con_DPrintf(" = %f\n", alpha);
437                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
438         }
439
440         for (x = 0;x < FOGWIDTH;x++)
441         {
442                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
443                 data1[x][0] = b;
444                 data1[x][1] = b;
445                 data1[x][2] = b;
446                 data1[x][3] = 255;
447                 //data2[x][0] = 255 - b;
448                 //data2[x][1] = 255 - b;
449                 //data2[x][2] = 255 - b;
450                 //data2[x][3] = 255;
451         }
452         if (r_texture_fogattenuation)
453         {
454                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
455                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
456         }
457         else
458         {
459                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
460                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
461         }
462 }
463
464 //=======================================================================================================================================================
465
466 static const char *builtinshaderstring =
467 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
468 "// written by Forest 'LordHavoc' Hale\n"
469 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
470 "\n"
471 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
472 "# define USEFOG\n"
473 "#endif\n"
474 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
475 "#define USELIGHTMAP\n"
476 "#endif\n"
477 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
478 "#define USEEYEVECTOR\n"
479 "#endif\n"
480 "\n"
481 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
482 "# extension GL_ARB_texture_rectangle : enable\n"
483 "#endif\n"
484 "\n"
485 "#ifdef USESHADOWMAP2D\n"
486 "# ifdef GL_EXT_gpu_shader4\n"
487 "#   extension GL_EXT_gpu_shader4 : enable\n"
488 "# endif\n"
489 "# ifdef GL_ARB_texture_gather\n"
490 "#   extension GL_ARB_texture_gather : enable\n"
491 "# else\n"
492 "#   ifdef GL_AMD_texture_texture4\n"
493 "#     extension GL_AMD_texture_texture4 : enable\n"
494 "#   endif\n"
495 "# endif\n"
496 "#endif\n"
497 "\n"
498 "#ifdef USESHADOWMAPCUBE\n"
499 "# extension GL_EXT_gpu_shader4 : enable\n"
500 "#endif\n"
501 "\n"
502 "//#ifdef USESHADOWSAMPLER\n"
503 "//# extension GL_ARB_shadow : enable\n"
504 "//#endif\n"
505 "\n"
506 "//#ifdef __GLSL_CG_DATA_TYPES\n"
507 "//# define myhalf half\n"
508 "//# define myhalf2 half2\n"
509 "//# define myhalf3 half3\n"
510 "//# define myhalf4 half4\n"
511 "//#else\n"
512 "# define myhalf float\n"
513 "# define myhalf2 vec2\n"
514 "# define myhalf3 vec3\n"
515 "# define myhalf4 vec4\n"
516 "//#endif\n"
517 "\n"
518 "#ifdef VERTEX_SHADER\n"
519 "uniform mat4 ModelViewProjectionMatrix;\n"
520 "#endif\n"
521 "\n"
522 "#ifdef MODE_DEPTH_OR_SHADOW\n"
523 "#ifdef VERTEX_SHADER\n"
524 "void main(void)\n"
525 "{\n"
526 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
527 "}\n"
528 "#endif\n"
529 "#else // !MODE_DEPTH_ORSHADOW\n"
530 "\n"
531 "\n"
532 "\n"
533 "\n"
534 "#ifdef MODE_SHOWDEPTH\n"
535 "#ifdef VERTEX_SHADER\n"
536 "void main(void)\n"
537 "{\n"
538 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
539 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
540 "}\n"
541 "#endif\n"
542 "\n"
543 "#ifdef FRAGMENT_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_FragColor = gl_Color;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_SHOWDEPTH\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_POSTPROCESS\n"
555 "varying vec2 TexCoord1;\n"
556 "varying vec2 TexCoord2;\n"
557 "\n"
558 "#ifdef VERTEX_SHADER\n"
559 "void main(void)\n"
560 "{\n"
561 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
562 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
563 "#ifdef USEBLOOM\n"
564 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
565 "#endif\n"
566 "}\n"
567 "#endif\n"
568 "\n"
569 "#ifdef FRAGMENT_SHADER\n"
570 "uniform sampler2D Texture_First;\n"
571 "#ifdef USEBLOOM\n"
572 "uniform sampler2D Texture_Second;\n"
573 "#endif\n"
574 "#ifdef USEGAMMARAMPS\n"
575 "uniform sampler2D Texture_GammaRamps;\n"
576 "#endif\n"
577 "#ifdef USESATURATION\n"
578 "uniform float Saturation;\n"
579 "#endif\n"
580 "#ifdef USEVIEWTINT\n"
581 "uniform vec4 ViewTintColor;\n"
582 "#endif\n"
583 "//uncomment these if you want to use them:\n"
584 "uniform vec4 UserVec1;\n"
585 "// uniform vec4 UserVec2;\n"
586 "// uniform vec4 UserVec3;\n"
587 "// uniform vec4 UserVec4;\n"
588 "// uniform float ClientTime;\n"
589 "uniform vec2 PixelSize;\n"
590 "void main(void)\n"
591 "{\n"
592 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
593 "#ifdef USEBLOOM\n"
594 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
595 "#endif\n"
596 "#ifdef USEVIEWTINT\n"
597 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
598 "#endif\n"
599 "\n"
600 "#ifdef USEPOSTPROCESSING\n"
601 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
602 "// 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"
603 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
604 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
605 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
606 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
607 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
608 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
609 "#endif\n"
610 "\n"
611 "#ifdef USESATURATION\n"
612 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
613 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
614 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
615 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
616 "#endif\n"
617 "\n"
618 "#ifdef USEGAMMARAMPS\n"
619 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
620 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
621 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
622 "#endif\n"
623 "}\n"
624 "#endif\n"
625 "#else // !MODE_POSTPROCESS\n"
626 "\n"
627 "\n"
628 "\n"
629 "\n"
630 "#ifdef MODE_GENERIC\n"
631 "#ifdef USEDIFFUSE\n"
632 "varying vec2 TexCoord1;\n"
633 "#endif\n"
634 "#ifdef USESPECULAR\n"
635 "varying vec2 TexCoord2;\n"
636 "#endif\n"
637 "#ifdef VERTEX_SHADER\n"
638 "void main(void)\n"
639 "{\n"
640 "       gl_FrontColor = gl_Color;\n"
641 "#ifdef USEDIFFUSE\n"
642 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
643 "#endif\n"
644 "#ifdef USESPECULAR\n"
645 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
646 "#endif\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "}\n"
649 "#endif\n"
650 "\n"
651 "#ifdef FRAGMENT_SHADER\n"
652 "#ifdef USEDIFFUSE\n"
653 "uniform sampler2D Texture_First;\n"
654 "#endif\n"
655 "#ifdef USESPECULAR\n"
656 "uniform sampler2D Texture_Second;\n"
657 "#endif\n"
658 "\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "#ifdef USEDIFFUSE\n"
663 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
664 "#endif\n"
665 "\n"
666 "#ifdef USESPECULAR\n"
667 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
668 "# ifdef USECOLORMAPPING\n"
669 "       gl_FragColor *= tex2;\n"
670 "# endif\n"
671 "# ifdef USEGLOW\n"
672 "       gl_FragColor += tex2;\n"
673 "# endif\n"
674 "# ifdef USEVERTEXTEXTUREBLEND\n"
675 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
676 "# endif\n"
677 "#endif\n"
678 "}\n"
679 "#endif\n"
680 "#else // !MODE_GENERIC\n"
681 "\n"
682 "\n"
683 "\n"
684 "\n"
685 "#ifdef MODE_BLOOMBLUR\n"
686 "varying TexCoord;\n"
687 "#ifdef VERTEX_SHADER\n"
688 "void main(void)\n"
689 "{\n"
690 "       gl_FrontColor = gl_Color;\n"
691 "       TexCoord = gl_MultiTexCoord0.xy;\n"
692 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
693 "}\n"
694 "#endif\n"
695 "\n"
696 "#ifdef FRAGMENT_SHADER\n"
697 "uniform sampler2D Texture_First;\n"
698 "uniform vec4 BloomBlur_Parameters;\n"
699 "\n"
700 "void main(void)\n"
701 "{\n"
702 "       int i;\n"
703 "       vec2 tc = TexCoord;\n"
704 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
705 "       tc += BloomBlur_Parameters.xy;\n"
706 "       for (i = 1;i < SAMPLES;i++)\n"
707 "       {\n"
708 "               color += texture2D(Texture_First, tc).rgb;\n"
709 "               tc += BloomBlur_Parameters.xy;\n"
710 "       }\n"
711 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
712 "}\n"
713 "#endif\n"
714 "#else // !MODE_BLOOMBLUR\n"
715 "#ifdef MODE_REFRACTION\n"
716 "varying vec2 TexCoord;\n"
717 "varying vec4 ModelViewProjectionPosition;\n"
718 "uniform mat4 TexMatrix;\n"
719 "#ifdef VERTEX_SHADER\n"
720 "\n"
721 "void main(void)\n"
722 "{\n"
723 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
724 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
725 "       ModelViewProjectionPosition = gl_Position;\n"
726 "}\n"
727 "#endif\n"
728 "\n"
729 "#ifdef FRAGMENT_SHADER\n"
730 "uniform sampler2D Texture_Normal;\n"
731 "uniform sampler2D Texture_Refraction;\n"
732 "uniform sampler2D Texture_Reflection;\n"
733 "\n"
734 "uniform vec4 DistortScaleRefractReflect;\n"
735 "uniform vec4 ScreenScaleRefractReflect;\n"
736 "uniform vec4 ScreenCenterRefractReflect;\n"
737 "uniform vec4 RefractColor;\n"
738 "uniform vec4 ReflectColor;\n"
739 "uniform float ReflectFactor;\n"
740 "uniform float ReflectOffset;\n"
741 "\n"
742 "void main(void)\n"
743 "{\n"
744 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
745 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
746 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
747 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
748 "       // FIXME temporary hack to detect the case that the reflection\n"
749 "       // gets blackened at edges due to leaving the area that contains actual\n"
750 "       // content.\n"
751 "       // Remove this 'ack once we have a better way to stop this thing from\n"
752 "       // 'appening.\n"
753 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
754 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
755 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
756 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
757 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
758 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
759 "}\n"
760 "#endif\n"
761 "#else // !MODE_REFRACTION\n"
762 "\n"
763 "\n"
764 "\n"
765 "\n"
766 "#ifdef MODE_WATER\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec3 EyeVector;\n"
769 "varying vec4 ModelViewProjectionPosition;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "uniform vec3 EyePosition;\n"
772 "uniform mat4 TexMatrix;\n"
773 "\n"
774 "void main(void)\n"
775 "{\n"
776 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
777 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
778 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
779 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
780 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
781 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
782 "       ModelViewProjectionPosition = gl_Position;\n"
783 "}\n"
784 "#endif\n"
785 "\n"
786 "#ifdef FRAGMENT_SHADER\n"
787 "uniform sampler2D Texture_Normal;\n"
788 "uniform sampler2D Texture_Refraction;\n"
789 "uniform sampler2D Texture_Reflection;\n"
790 "\n"
791 "uniform vec4 DistortScaleRefractReflect;\n"
792 "uniform vec4 ScreenScaleRefractReflect;\n"
793 "uniform vec4 ScreenCenterRefractReflect;\n"
794 "uniform vec4 RefractColor;\n"
795 "uniform vec4 ReflectColor;\n"
796 "uniform float ReflectFactor;\n"
797 "uniform float ReflectOffset;\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
802 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
803 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
804 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
805 "       // FIXME temporary hack to detect the case that the reflection\n"
806 "       // gets blackened at edges due to leaving the area that contains actual\n"
807 "       // content.\n"
808 "       // Remove this 'ack once we have a better way to stop this thing from\n"
809 "       // 'appening.\n"
810 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
811 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
812 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
813 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
814 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
815 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
816 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
817 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
818 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
819 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
820 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
821 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
822 "}\n"
823 "#endif\n"
824 "#else // !MODE_WATER\n"
825 "\n"
826 "\n"
827 "\n"
828 "\n"
829 "// common definitions between vertex shader and fragment shader:\n"
830 "\n"
831 "varying vec2 TexCoord;\n"
832 "#ifdef USEVERTEXTEXTUREBLEND\n"
833 "varying vec2 TexCoord2;\n"
834 "#endif\n"
835 "#ifdef USELIGHTMAP\n"
836 "varying vec2 TexCoordLightmap;\n"
837 "#endif\n"
838 "\n"
839 "#ifdef MODE_LIGHTSOURCE\n"
840 "varying vec3 CubeVector;\n"
841 "#endif\n"
842 "\n"
843 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
844 "varying vec3 LightVector;\n"
845 "#endif\n"
846 "\n"
847 "#ifdef USEEYEVECTOR\n"
848 "varying vec3 EyeVector;\n"
849 "#endif\n"
850 "#ifdef USEFOG\n"
851 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
852 "#endif\n"
853 "\n"
854 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
855 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
856 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
857 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
858 "#endif\n"
859 "\n"
860 "#ifdef USEREFLECTION\n"
861 "varying vec4 ModelViewProjectionPosition;\n"
862 "#endif\n"
863 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
864 "uniform vec3 LightPosition;\n"
865 "varying vec4 ModelViewPosition;\n"
866 "#endif\n"
867 "\n"
868 "#ifdef MODE_LIGHTSOURCE\n"
869 "uniform vec3 LightPosition;\n"
870 "#endif\n"
871 "uniform vec3 EyePosition;\n"
872 "#ifdef MODE_LIGHTDIRECTION\n"
873 "uniform vec3 LightDir;\n"
874 "#endif\n"
875 "uniform vec4 FogPlane;\n"
876 "\n"
877 "\n"
878 "\n"
879 "\n"
880 "\n"
881 "// 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"
882 "\n"
883 "// fragment shader specific:\n"
884 "#ifdef FRAGMENT_SHADER\n"
885 "\n"
886 "uniform sampler2D Texture_Normal;\n"
887 "uniform sampler2D Texture_Color;\n"
888 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
889 "uniform sampler2D Texture_Gloss;\n"
890 "//#endif\n"
891 "#ifdef USEGLOW\n"
892 "uniform sampler2D Texture_Glow;\n"
893 "#endif\n"
894 "#ifdef USEVERTEXTEXTUREBLEND\n"
895 "uniform sampler2D Texture_SecondaryNormal;\n"
896 "uniform sampler2D Texture_SecondaryColor;\n"
897 "//#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
898 "uniform sampler2D Texture_SecondaryGloss;\n"
899 "//#endif\n"
900 "#ifdef USEGLOW\n"
901 "uniform sampler2D Texture_SecondaryGlow;\n"
902 "#endif\n"
903 "#endif\n"
904 "#ifdef USECOLORMAPPING\n"
905 "uniform sampler2D Texture_Pants;\n"
906 "uniform sampler2D Texture_Shirt;\n"
907 "#endif\n"
908 "#ifdef USEFOG\n"
909 "uniform sampler2D Texture_FogMask;\n"
910 "#endif\n"
911 "#ifdef USELIGHTMAP\n"
912 "uniform sampler2D Texture_Lightmap;\n"
913 "#endif\n"
914 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
915 "uniform sampler2D Texture_Deluxemap;\n"
916 "#endif\n"
917 "#ifdef USEREFLECTION\n"
918 "uniform sampler2D Texture_Reflection;\n"
919 "#endif\n"
920 "\n"
921 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
922 "uniform sampler2D Texture_ScreenDepth;\n"
923 "uniform sampler2D Texture_ScreenNormalMap;\n"
924 "#endif\n"
925 "#ifdef USEDEFERREDLIGHTMAP\n"
926 "uniform sampler2D Texture_ScreenDiffuse;\n"
927 "uniform sampler2D Texture_ScreenSpecular;\n"
928 "#endif\n"
929 "\n"
930 "uniform myhalf3 Color_Pants;\n"
931 "uniform myhalf3 Color_Shirt;\n"
932 "uniform myhalf3 FogColor;\n"
933 "\n"
934 "#ifdef USEFOG\n"
935 "uniform float FogRangeRecip;\n"
936 "uniform float FogPlaneViewDist;\n"
937 "uniform float FogHeightFade;\n"
938 "float FogVertex(void)\n"
939 "{\n"
940 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
941 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
942 "       float fogfrac;\n"
943 "#ifdef USEFOGOUTSIDE\n"
944 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
945 "#else\n"
946 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
947 "#endif\n"
948 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
949 "}\n"
950 "#endif\n"
951 "\n"
952 "#ifdef USEOFFSETMAPPING\n"
953 "uniform float OffsetMapping_Scale;\n"
954 "vec2 OffsetMapping(vec2 TexCoord)\n"
955 "{\n"
956 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
957 "       // 14 sample relief mapping: linear search and then binary search\n"
958 "       // this basically steps forward a small amount repeatedly until it finds\n"
959 "       // itself inside solid, then jitters forward and back using decreasing\n"
960 "       // amounts to find the impact\n"
961 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
962 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
963 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
964 "       vec3 RT = vec3(TexCoord, 1);\n"
965 "       OffsetVector *= 0.1;\n"
966 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
967 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
968 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
969 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
970 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
971 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
972 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
973 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
974 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
975 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
976 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
977 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
978 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
979 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
980 "       return RT.xy;\n"
981 "#else\n"
982 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
983 "       // this basically moves forward the full distance, and then backs up based\n"
984 "       // on height of samples\n"
985 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
986 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
987 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
988 "       TexCoord += OffsetVector;\n"
989 "       OffsetVector *= 0.333;\n"
990 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
991 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
992 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
993 "       return TexCoord;\n"
994 "#endif\n"
995 "}\n"
996 "#endif // USEOFFSETMAPPING\n"
997 "\n"
998 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
999 "uniform sampler2D Texture_Attenuation;\n"
1000 "uniform samplerCube Texture_Cube;\n"
1001 "\n"
1002 "#ifdef USESHADOWMAPRECT\n"
1003 "# ifdef USESHADOWSAMPLER\n"
1004 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1005 "# else\n"
1006 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1007 "# endif\n"
1008 "#endif\n"
1009 "\n"
1010 "#ifdef USESHADOWMAP2D\n"
1011 "# ifdef USESHADOWSAMPLER\n"
1012 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1013 "# else\n"
1014 "uniform sampler2D Texture_ShadowMap2D;\n"
1015 "# endif\n"
1016 "#endif\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPVSDCT\n"
1019 "uniform samplerCube Texture_CubeProjection;\n"
1020 "#endif\n"
1021 "\n"
1022 "#ifdef USESHADOWMAPCUBE\n"
1023 "# ifdef USESHADOWSAMPLER\n"
1024 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1025 "# else\n"
1026 "uniform samplerCube Texture_ShadowMapCube;\n"
1027 "# endif\n"
1028 "#endif\n"
1029 "\n"
1030 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1031 "uniform vec2 ShadowMap_TextureScale;\n"
1032 "uniform vec4 ShadowMap_Parameters;\n"
1033 "#endif\n"
1034 "\n"
1035 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1036 "# ifndef USESHADOWMAPVSDCT\n"
1037 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1038 "{\n"
1039 "       vec3 adir = abs(dir);\n"
1040 "       vec2 tc;\n"
1041 "       vec2 offset;\n"
1042 "       float ma;\n"
1043 "       if (adir.x > adir.y)\n"
1044 "       {\n"
1045 "               if (adir.x > adir.z) // X\n"
1046 "               {\n"
1047 "                       ma = adir.x;\n"
1048 "                       tc = dir.zy;\n"
1049 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1050 "               }\n"
1051 "               else // Z\n"
1052 "               {\n"
1053 "                       ma = adir.z;\n"
1054 "                       tc = dir.xy;\n"
1055 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1056 "               }\n"
1057 "       }\n"
1058 "       else\n"
1059 "       {\n"
1060 "               if (adir.y > adir.z) // Y\n"
1061 "               {\n"
1062 "                       ma = adir.y;\n"
1063 "                       tc = dir.xz;\n"
1064 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1065 "               }\n"
1066 "               else // Z\n"
1067 "               {\n"
1068 "                       ma = adir.z;\n"
1069 "                       tc = dir.xy;\n"
1070 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1071 "               }\n"
1072 "       }\n"
1073 "\n"
1074 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1075 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1076 "       stc.z += ShadowMap_Parameters.z;\n"
1077 "       return stc;\n"
1078 "}\n"
1079 "# else\n"
1080 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1081 "{\n"
1082 "       vec3 adir = abs(dir);\n"
1083 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1084 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
1085 "       vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1086 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1087 "       stc.z += ShadowMap_Parameters.z;\n"
1088 "       return stc;\n"
1089 "}\n"
1090 "# endif\n"
1091 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1092 "\n"
1093 "#ifdef USESHADOWMAPCUBE\n"
1094 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1095 "{\n"
1096 "       vec3 adir = abs(dir);\n"
1097 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1098 "}\n"
1099 "#endif\n"
1100 "\n"
1101 "# ifdef USESHADOWMAPRECT\n"
1102 "float ShadowMapCompare(vec3 dir)\n"
1103 "{\n"
1104 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1105 "       float f;\n"
1106 "#  ifdef USESHADOWSAMPLER\n"
1107 "\n"
1108 "#    ifdef USESHADOWMAPPCF\n"
1109 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1110 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1111 "#    else\n"
1112 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1113 "#    endif\n"
1114 "\n"
1115 "#  else\n"
1116 "\n"
1117 "#    ifdef USESHADOWMAPPCF\n"
1118 "#      if USESHADOWMAPPCF > 1\n"
1119 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1120 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1121 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1122 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1123 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1124 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1125 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1126 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1127 "#      else\n"
1128 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1129 "       vec2 offset = fract(shadowmaptc.xy);\n"
1130 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1131 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1132 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1133 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1134 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1135 "#      endif\n"
1136 "#    else\n"
1137 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1138 "#    endif\n"
1139 "\n"
1140 "#  endif\n"
1141 "       return f;\n"
1142 "}\n"
1143 "# endif\n"
1144 "\n"
1145 "# ifdef USESHADOWMAP2D\n"
1146 "float ShadowMapCompare(vec3 dir)\n"
1147 "{\n"
1148 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1149 "       float f;\n"
1150 "\n"
1151 "#  ifdef USESHADOWSAMPLER\n"
1152 "#    ifdef USESHADOWMAPPCF\n"
1153 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1154 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1155 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1156 "#    else\n"
1157 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1158 "#    endif\n"
1159 "#  else\n"
1160 "#    ifdef USESHADOWMAPPCF\n"
1161 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1162 "#      ifdef GL_ARB_texture_gather\n"
1163 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1164 "#      else\n"
1165 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1166 "#      endif\n"
1167 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1168 "       center *= ShadowMap_TextureScale;\n"
1169 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1170 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1171 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1172 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1173 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1174 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1175 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1176 "#     else\n"
1177 "#      ifdef GL_EXT_gpu_shader4\n"
1178 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1179 "#      else\n"
1180 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1181 "#      endif\n"
1182 "#      if USESHADOWMAPPCF > 1\n"
1183 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1184 "       center *= ShadowMap_TextureScale;\n"
1185 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1186 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1187 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1188 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1189 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1190 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1191 "#      else\n"
1192 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1193 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1194 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1195 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1196 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1197 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1198 "#      endif\n"
1199 "#     endif\n"
1200 "#    else\n"
1201 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1202 "#    endif\n"
1203 "#  endif\n"
1204 "       return f;\n"
1205 "}\n"
1206 "# endif\n"
1207 "\n"
1208 "# ifdef USESHADOWMAPCUBE\n"
1209 "float ShadowMapCompare(vec3 dir)\n"
1210 "{\n"
1211 "       // apply depth texture cubemap as light filter\n"
1212 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1213 "       float f;\n"
1214 "#  ifdef USESHADOWSAMPLER\n"
1215 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1216 "#  else\n"
1217 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1218 "#  endif\n"
1219 "       return f;\n"
1220 "}\n"
1221 "# endif\n"
1222 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
1223 "#endif // FRAGMENT_SHADER\n"
1224 "\n"
1225 "\n"
1226 "\n"
1227 "\n"
1228 "#ifdef MODE_DEFERREDGEOMETRY\n"
1229 "#ifdef VERTEX_SHADER\n"
1230 "uniform mat4 TexMatrix;\n"
1231 "#ifdef USEVERTEXTEXTUREBLEND\n"
1232 "uniform mat4 BackgroundTexMatrix;\n"
1233 "#endif\n"
1234 "uniform mat4 ModelViewMatrix;\n"
1235 "void main(void)\n"
1236 "{\n"
1237 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1238 "#ifdef USEVERTEXTEXTUREBLEND\n"
1239 "       gl_FrontColor = gl_Color;\n"
1240 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1241 "#endif\n"
1242 "\n"
1243 "       // transform unnormalized eye direction into tangent space\n"
1244 "#ifdef USEOFFSETMAPPING\n"
1245 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1249 "#endif\n"
1250 "\n"
1251 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1252 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1253 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1254 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1255 "}\n"
1256 "#endif // VERTEX_SHADER\n"
1257 "\n"
1258 "#ifdef FRAGMENT_SHADER\n"
1259 "void main(void)\n"
1260 "{\n"
1261 "#ifdef USEOFFSETMAPPING\n"
1262 "       // apply offsetmapping\n"
1263 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1264 "#define TexCoord TexCoordOffset\n"
1265 "#endif\n"
1266 "\n"
1267 "#ifdef USEALPHAKILL\n"
1268 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1269 "               discard;\n"
1270 "#endif\n"
1271 "\n"
1272 "#ifdef USEVERTEXTEXTUREBLEND\n"
1273 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1274 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1275 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1276 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1277 "#endif\n"
1278 "\n"
1279 "#ifdef USEVERTEXTEXTUREBLEND\n"
1280 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1281 "#else\n"
1282 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1283 "#endif\n"
1284 "\n"
1285 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), 1);\n"
1286 "}\n"
1287 "#endif // FRAGMENT_SHADER\n"
1288 "#else // !MODE_DEFERREDGEOMETRY\n"
1289 "\n"
1290 "\n"
1291 "\n"
1292 "\n"
1293 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1294 "#ifdef VERTEX_SHADER\n"
1295 "uniform mat4 ModelViewMatrix;\n"
1296 "void main(void)\n"
1297 "{\n"
1298 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1299 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1300 "}\n"
1301 "#endif // VERTEX_SHADER\n"
1302 "\n"
1303 "#ifdef FRAGMENT_SHADER\n"
1304 "uniform mat4 ViewToLight;\n"
1305 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1306 "uniform vec2 ScreenToDepth;\n"
1307 "uniform myhalf3 DeferredColor_Ambient;\n"
1308 "uniform myhalf3 DeferredColor_Diffuse;\n"
1309 "#ifdef USESPECULAR\n"
1310 "uniform myhalf3 DeferredColor_Specular;\n"
1311 "uniform myhalf SpecularPower;\n"
1312 "#endif\n"
1313 "uniform myhalf2 PixelToScreenTexCoord;\n"
1314 "void main(void)\n"
1315 "{\n"
1316 "       // calculate viewspace pixel position\n"
1317 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1318 "       vec3 position;\n"
1319 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1320 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1321 "       // decode viewspace pixel normal\n"
1322 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1323 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1324 "       // surfacenormal = pixel normal in viewspace\n"
1325 "       // LightVector = pixel to light in viewspace\n"
1326 "       // CubeVector = position in lightspace\n"
1327 "       // eyevector = pixel to view in viewspace\n"
1328 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1329 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1330 "#ifdef USEDIFFUSE\n"
1331 "       // calculate diffuse shading\n"
1332 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1333 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1334 "#endif\n"
1335 "#ifdef USESPECULAR\n"
1336 "       // calculate directional shading\n"
1337 "       vec3 eyevector = position * -1.0;\n"
1338 "#  ifdef USEEXACTSPECULARMATH\n"
1339 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
1340 "#  else\n"
1341 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1343 "#  endif\n"
1344 "#endif\n"
1345 "\n"
1346 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1347 "       fade *= ShadowMapCompare(CubeVector);\n"
1348 "#endif\n"
1349 "\n"
1350 "#ifdef USEDIFFUSE\n"
1351 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1352 "#else\n"
1353 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1354 "#endif\n"
1355 "#ifdef USESPECULAR\n"
1356 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1357 "#else\n"
1358 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1359 "#endif\n"
1360 "\n"
1361 "# ifdef USECUBEFILTER\n"
1362 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1363 "       gl_FragData[0].rgb *= cubecolor;\n"
1364 "       gl_FragData[1].rgb *= cubecolor;\n"
1365 "# endif\n"
1366 "}\n"
1367 "#endif // FRAGMENT_SHADER\n"
1368 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1369 "\n"
1370 "\n"
1371 "\n"
1372 "\n"
1373 "#ifdef VERTEX_SHADER\n"
1374 "uniform mat4 TexMatrix;\n"
1375 "#ifdef USEVERTEXTEXTUREBLEND\n"
1376 "uniform mat4 BackgroundTexMatrix;\n"
1377 "#endif\n"
1378 "#ifdef MODE_LIGHTSOURCE\n"
1379 "uniform mat4 ModelToLight;\n"
1380 "#endif\n"
1381 "void main(void)\n"
1382 "{\n"
1383 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1384 "       gl_FrontColor = gl_Color;\n"
1385 "#endif\n"
1386 "       // copy the surface texcoord\n"
1387 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1388 "#ifdef USEVERTEXTEXTUREBLEND\n"
1389 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1390 "#endif\n"
1391 "#ifdef USELIGHTMAP\n"
1392 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1393 "#endif\n"
1394 "\n"
1395 "#ifdef MODE_LIGHTSOURCE\n"
1396 "       // transform vertex position into light attenuation/cubemap space\n"
1397 "       // (-1 to +1 across the light box)\n"
1398 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1399 "\n"
1400 "# ifdef USEDIFFUSE\n"
1401 "       // transform unnormalized light direction into tangent space\n"
1402 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1403 "       //  normalize it per pixel)\n"
1404 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1405 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1406 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1407 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1408 "# endif\n"
1409 "#endif\n"
1410 "\n"
1411 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1412 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1413 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1414 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1415 "#endif\n"
1416 "\n"
1417 "       // transform unnormalized eye direction into tangent space\n"
1418 "#ifdef USEEYEVECTOR\n"
1419 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1420 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1421 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1422 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1423 "#endif\n"
1424 "\n"
1425 "#ifdef USEFOG\n"
1426 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1427 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1431 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1432 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1433 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1434 "#endif\n"
1435 "\n"
1436 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1437 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1438 "\n"
1439 "#ifdef USEREFLECTION\n"
1440 "       ModelViewProjectionPosition = gl_Position;\n"
1441 "#endif\n"
1442 "}\n"
1443 "#endif // VERTEX_SHADER\n"
1444 "\n"
1445 "\n"
1446 "\n"
1447 "\n"
1448 "#ifdef FRAGMENT_SHADER\n"
1449 "#ifdef USEDEFERREDLIGHTMAP\n"
1450 "uniform myhalf2 PixelToScreenTexCoord;\n"
1451 "uniform myhalf3 DeferredMod_Diffuse;\n"
1452 "uniform myhalf3 DeferredMod_Specular;\n"
1453 "#endif\n"
1454 "uniform myhalf3 Color_Ambient;\n"
1455 "uniform myhalf3 Color_Diffuse;\n"
1456 "uniform myhalf3 Color_Specular;\n"
1457 "uniform myhalf SpecularPower;\n"
1458 "#ifdef USEGLOW\n"
1459 "uniform myhalf3 Color_Glow;\n"
1460 "#endif\n"
1461 "uniform myhalf Alpha;\n"
1462 "#ifdef USEREFLECTION\n"
1463 "uniform vec4 DistortScaleRefractReflect;\n"
1464 "uniform vec4 ScreenScaleRefractReflect;\n"
1465 "uniform vec4 ScreenCenterRefractReflect;\n"
1466 "uniform myhalf4 ReflectColor;\n"
1467 "#endif\n"
1468 "#ifdef MODE_LIGHTDIRECTION\n"
1469 "uniform myhalf3 LightColor;\n"
1470 "#endif\n"
1471 "#ifdef MODE_LIGHTSOURCE\n"
1472 "uniform myhalf3 LightColor;\n"
1473 "#endif\n"
1474 "void main(void)\n"
1475 "{\n"
1476 "#ifdef USEOFFSETMAPPING\n"
1477 "       // apply offsetmapping\n"
1478 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1479 "#define TexCoord TexCoordOffset\n"
1480 "#endif\n"
1481 "\n"
1482 "       // combine the diffuse textures (base, pants, shirt)\n"
1483 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1484 "#ifdef USEALPHAKILL\n"
1485 "       if (color.a < 0.5)\n"
1486 "               discard;\n"
1487 "#endif\n"
1488 "       color.a *= Alpha;\n"
1489 "#ifdef USECOLORMAPPING\n"
1490 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1491 "#endif\n"
1492 "#ifdef USEVERTEXTEXTUREBLEND\n"
1493 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1494 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1495 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1496 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1497 "       color.a = 1.0;\n"
1498 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1499 "#endif\n"
1500 "\n"
1501 "       // get the surface normal\n"
1502 "#ifdef USEVERTEXTEXTUREBLEND\n"
1503 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1504 "#else\n"
1505 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1506 "#endif\n"
1507 "\n"
1508 "       // get the material colors\n"
1509 "       myhalf3 diffusetex = color.rgb;\n"
1510 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1511 "# ifdef USEVERTEXTEXTUREBLEND\n"
1512 "       myhalf3 glosstex = mix(myhalf3(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf3(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1513 "# else\n"
1514 "       myhalf3 glosstex = myhalf3(texture2D(Texture_Gloss, TexCoord));\n"
1515 "# endif\n"
1516 "#endif\n"
1517 "\n"
1518 "\n"
1519 "\n"
1520 "\n"
1521 "#ifdef MODE_LIGHTSOURCE\n"
1522 "       // light source\n"
1523 "#ifdef USEDIFFUSE\n"
1524 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1525 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1526 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1527 "#ifdef USESPECULAR\n"
1528 "#ifdef USEEXACTSPECULARMATH\n"
1529 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1530 "#else\n"
1531 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1532 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1533 "#endif\n"
1534 "       color.rgb += glosstex * (specular * Color_Specular);\n"
1535 "#endif\n"
1536 "#else\n"
1537 "       color.rgb = diffusetex * Color_Ambient;\n"
1538 "#endif\n"
1539 "       color.rgb *= LightColor;\n"
1540 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1541 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1542 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1543 "#endif\n"
1544 "# ifdef USECUBEFILTER\n"
1545 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1546 "# endif\n"
1547 "#endif // MODE_LIGHTSOURCE\n"
1548 "\n"
1549 "\n"
1550 "\n"
1551 "\n"
1552 "#ifdef MODE_LIGHTDIRECTION\n"
1553 "#define SHADING\n"
1554 "#ifdef USEDIFFUSE\n"
1555 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1556 "#endif\n"
1557 "#define lightcolor LightColor\n"
1558 "#endif // MODE_LIGHTDIRECTION\n"
1559 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1560 "#define SHADING\n"
1561 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1562 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1563 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1564 "       // convert modelspace light vector to tangentspace\n"
1565 "       myhalf3 lightnormal;\n"
1566 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1567 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1568 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1569 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1570 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1571 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1572 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1573 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1574 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1575 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1576 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1577 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1578 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1579 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1580 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1581 "#define SHADING\n"
1582 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1583 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1584 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1585 "#endif\n"
1586 "\n"
1587 "\n"
1588 "\n"
1589 "\n"
1590 "#ifdef MODE_LIGHTMAP\n"
1591 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1592 "#endif // MODE_LIGHTMAP\n"
1593 "#ifdef MODE_VERTEXCOLOR\n"
1594 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1595 "#endif // MODE_VERTEXCOLOR\n"
1596 "#ifdef MODE_FLATCOLOR\n"
1597 "       color.rgb = diffusetex * Color_Ambient;\n"
1598 "#endif // MODE_FLATCOLOR\n"
1599 "\n"
1600 "\n"
1601 "\n"
1602 "\n"
1603 "#ifdef SHADING\n"
1604 "# ifdef USEDIFFUSE\n"
1605 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1606 "#  ifdef USESPECULAR\n"
1607 "#   ifdef USEEXACTSPECULARMATH\n"
1608 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
1609 "#   else\n"
1610 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1611 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
1612 "#   endif\n"
1613 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
1614 "#  else\n"
1615 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1616 "#  endif\n"
1617 "# else\n"
1618 "       color.rgb = diffusetex * Color_Ambient;\n"
1619 "# endif\n"
1620 "#endif\n"
1621 "\n"
1622 "#ifdef USEDEFERREDLIGHTMAP\n"
1623 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1624 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1625 "       color.rgb += glosstex * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1626 "#endif\n"
1627 "\n"
1628 "#ifdef USEGLOW\n"
1629 "#ifdef USEVERTEXTEXTUREBLEND\n"
1630 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1631 "#else\n"
1632 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1633 "#endif\n"
1634 "#endif\n"
1635 "\n"
1636 "#ifdef USEFOG\n"
1637 "#ifdef MODE_LIGHTSOURCE\n"
1638 "       color.rgb *= myhalf(FogVertex());\n"
1639 "#else\n"
1640 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1641 "#endif\n"
1642 "#endif\n"
1643 "\n"
1644 "       // 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"
1645 "#ifdef USEREFLECTION\n"
1646 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1647 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1648 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1649 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1650 "       // FIXME temporary hack to detect the case that the reflection\n"
1651 "       // gets blackened at edges due to leaving the area that contains actual\n"
1652 "       // content.\n"
1653 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1654 "       // 'appening.\n"
1655 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1656 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1657 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1658 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1659 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1660 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1661 "#endif\n"
1662 "\n"
1663 "       gl_FragColor = vec4(color);\n"
1664 "}\n"
1665 "#endif // FRAGMENT_SHADER\n"
1666 "\n"
1667 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1668 "#endif // !MODE_DEFERREDGEOMETRY\n"
1669 "#endif // !MODE_WATER\n"
1670 "#endif // !MODE_REFRACTION\n"
1671 "#endif // !MODE_BLOOMBLUR\n"
1672 "#endif // !MODE_GENERIC\n"
1673 "#endif // !MODE_POSTPROCESS\n"
1674 "#endif // !MODE_SHOWDEPTH\n"
1675 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1676 ;
1677
1678 /*
1679 =========================================================================================================================================================
1680
1681
1682
1683 =========================================================================================================================================================
1684
1685
1686
1687 =========================================================================================================================================================
1688
1689
1690
1691 =========================================================================================================================================================
1692
1693
1694
1695 =========================================================================================================================================================
1696
1697
1698
1699 =========================================================================================================================================================
1700
1701
1702
1703 =========================================================================================================================================================
1704 */
1705
1706 const char *builtincgshaderstring =
1707 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1708 "// written by Forest 'LordHavoc' Hale\n"
1709 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1710 "\n"
1711 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1712 "# define USEFOG\n"
1713 "#endif\n"
1714 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1715 "#define USELIGHTMAP\n"
1716 "#endif\n"
1717 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING)\n"
1718 "#define USEEYEVECTOR\n"
1719 "#endif\n"
1720 "\n"
1721 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1722 "#ifdef VERTEX_SHADER\n"
1723 "void main\n"
1724 "(\n"
1725 "float4 gl_Vertex : POSITION,\n"
1726 "uniform float4x4 ModelViewProjectionMatrix,\n"
1727 "out float4 gl_Position : POSITION\n"
1728 ")\n"
1729 "{\n"
1730 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1731 "}\n"
1732 "#endif\n"
1733 "#else // !MODE_DEPTH_ORSHADOW\n"
1734 "\n"
1735 "\n"
1736 "\n"
1737 "\n"
1738 "#ifdef MODE_SHOWDEPTH\n"
1739 "#ifdef VERTEX_SHADER\n"
1740 "void main\n"
1741 "(\n"
1742 "float4 gl_Vertex : POSITION,\n"
1743 "uniform float4x4 ModelViewProjectionMatrix,\n"
1744 "out float4 gl_Position : POSITION,\n"
1745 "out float4 gl_FrontColor : COLOR0\n"
1746 ")\n"
1747 "{\n"
1748 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1749 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1750 "}\n"
1751 "#endif\n"
1752 "\n"
1753 "#ifdef FRAGMENT_SHADER\n"
1754 "void main\n"
1755 "(\n"
1756 "float4 gl_FrontColor : COLOR0,\n"
1757 "out float4 gl_FragColor : COLOR\n"
1758 ")\n"
1759 "{\n"
1760 "       gl_FragColor = gl_FrontColor;\n"
1761 "}\n"
1762 "#endif\n"
1763 "#else // !MODE_SHOWDEPTH\n"
1764 "\n"
1765 "\n"
1766 "\n"
1767 "\n"
1768 "#ifdef MODE_POSTPROCESS\n"
1769 "\n"
1770 "#ifdef VERTEX_SHADER\n"
1771 "void main\n"
1772 "(\n"
1773 "float4 gl_Vertex : POSITION,\n"
1774 "uniform float4x4 ModelViewProjectionMatrix,\n"
1775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1777 "out float4 gl_Position : POSITION,\n"
1778 "out float2 TexCoord1 : TEXCOORD0,\n"
1779 "out float2 TexCoord2 : TEXCOORD1\n"
1780 ")\n"
1781 "{\n"
1782 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1783 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1784 "#ifdef USEBLOOM\n"
1785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1786 "#endif\n"
1787 "}\n"
1788 "#endif\n"
1789 "\n"
1790 "#ifdef FRAGMENT_SHADER\n"
1791 "void main\n"
1792 "(\n"
1793 "float2 TexCoord1 : TEXCOORD0,\n"
1794 "float2 TexCoord2 : TEXCOORD1,\n"
1795 "uniform sampler2D Texture_First,\n"
1796 "#ifdef USEBLOOM\n"
1797 "uniform sampler2D Texture_Second,\n"
1798 "#endif\n"
1799 "#ifdef USEGAMMARAMPS\n"
1800 "uniform sampler2D Texture_GammaRamps,\n"
1801 "#endif\n"
1802 "#ifdef USESATURATION\n"
1803 "uniform float Saturation,\n"
1804 "#endif\n"
1805 "#ifdef USEVIEWTINT\n"
1806 "uniform float4 ViewTintColor,\n"
1807 "#endif\n"
1808 "uniform float4 UserVec1,\n"
1809 "uniform float4 UserVec2,\n"
1810 "uniform float4 UserVec3,\n"
1811 "uniform float4 UserVec4,\n"
1812 "uniform float ClientTime,\n"
1813 "uniform float2 PixelSize,\n"
1814 "out float4 gl_FragColor : COLOR\n"
1815 ")\n"
1816 "{\n"
1817 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1818 "#ifdef USEBLOOM\n"
1819 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1820 "#endif\n"
1821 "#ifdef USEVIEWTINT\n"
1822 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1823 "#endif\n"
1824 "\n"
1825 "#ifdef USEPOSTPROCESSING\n"
1826 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1827 "// 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"
1828 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1829 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1830 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1831 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1832 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1833 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1834 "#endif\n"
1835 "\n"
1836 "#ifdef USESATURATION\n"
1837 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1838 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1839 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1840 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1841 "#endif\n"
1842 "\n"
1843 "#ifdef USEGAMMARAMPS\n"
1844 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1845 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1846 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1847 "#endif\n"
1848 "}\n"
1849 "#endif\n"
1850 "#else // !MODE_POSTPROCESS\n"
1851 "\n"
1852 "\n"
1853 "\n"
1854 "\n"
1855 "#ifdef MODE_GENERIC\n"
1856 "#ifdef VERTEX_SHADER\n"
1857 "void main\n"
1858 "(\n"
1859 "float4 gl_Vertex : POSITION,\n"
1860 "uniform float4x4 ModelViewProjectionMatrix,\n"
1861 "float4 gl_Color : COLOR0,\n"
1862 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1863 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1864 "out float4 gl_Position : POSITION,\n"
1865 "out float4 gl_FrontColor : COLOR,\n"
1866 "out float2 TexCoord1 : TEXCOORD0,\n"
1867 "out float2 TexCoord2 : TEXCOORD1\n"
1868 ")\n"
1869 "{\n"
1870 "       gl_FrontColor = gl_Color;\n"
1871 "#ifdef USEDIFFUSE\n"
1872 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1873 "#endif\n"
1874 "#ifdef USESPECULAR\n"
1875 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1876 "#endif\n"
1877 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1878 "}\n"
1879 "#endif\n"
1880 "\n"
1881 "#ifdef FRAGMENT_SHADER\n"
1882 "\n"
1883 "void main\n"
1884 "(\n"
1885 "float4 gl_FrontColor : COLOR,\n"
1886 "float2 TexCoord1 : TEXCOORD0,\n"
1887 "float2 TexCoord2 : TEXCOORD1,\n"
1888 "#ifdef USEDIFFUSE\n"
1889 "uniform sampler2D Texture_First,\n"
1890 "#endif\n"
1891 "#ifdef USESPECULAR\n"
1892 "uniform sampler2D Texture_Second,\n"
1893 "#endif\n"
1894 "out float4 gl_FragColor : COLOR\n"
1895 ")\n"
1896 "{\n"
1897 "       gl_FragColor = gl_FrontColor;\n"
1898 "#ifdef USEDIFFUSE\n"
1899 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1900 "#endif\n"
1901 "\n"
1902 "#ifdef USESPECULAR\n"
1903 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1904 "# ifdef USECOLORMAPPING\n"
1905 "       gl_FragColor *= tex2;\n"
1906 "# endif\n"
1907 "# ifdef USEGLOW\n"
1908 "       gl_FragColor += tex2;\n"
1909 "# endif\n"
1910 "# ifdef USEVERTEXTEXTUREBLEND\n"
1911 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1912 "# endif\n"
1913 "#endif\n"
1914 "}\n"
1915 "#endif\n"
1916 "#else // !MODE_GENERIC\n"
1917 "\n"
1918 "\n"
1919 "\n"
1920 "\n"
1921 "#ifdef MODE_BLOOMBLUR\n"
1922 "#ifdef VERTEX_SHADER\n"
1923 "void main\n"
1924 "(\n"
1925 "float4 gl_Vertex : POSITION,\n"
1926 "uniform float4x4 ModelViewProjectionMatrix,\n"
1927 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1928 "out float4 gl_Position : POSITION,\n"
1929 "out float2 TexCoord : TEXCOORD0\n"
1930 ")\n"
1931 "{\n"
1932 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1933 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1934 "}\n"
1935 "#endif\n"
1936 "\n"
1937 "#ifdef FRAGMENT_SHADER\n"
1938 "\n"
1939 "void main\n"
1940 "(\n"
1941 "float2 TexCoord : TEXCOORD0,\n"
1942 "uniform sampler2D Texture_First,\n"
1943 "uniform float4 BloomBlur_Parameters,\n"
1944 "out float4 gl_FragColor : COLOR\n"
1945 ")\n"
1946 "{\n"
1947 "       int i;\n"
1948 "       float2 tc = TexCoord;\n"
1949 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1950 "       tc += BloomBlur_Parameters.xy;\n"
1951 "       for (i = 1;i < SAMPLES;i++)\n"
1952 "       {\n"
1953 "               color += tex2D(Texture_First, tc).rgb;\n"
1954 "               tc += BloomBlur_Parameters.xy;\n"
1955 "       }\n"
1956 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1957 "}\n"
1958 "#endif\n"
1959 "#else // !MODE_BLOOMBLUR\n"
1960 "#ifdef MODE_REFRACTION\n"
1961 "#ifdef VERTEX_SHADER\n"
1962 "void main\n"
1963 "(\n"
1964 "float4 gl_Vertex : POSITION,\n"
1965 "uniform float4x4 ModelViewProjectionMatrix,\n"
1966 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1967 "uniform float4x4 TexMatrix,\n"
1968 "uniform float3 EyePosition,\n"
1969 "out float4 gl_Position : POSITION,\n"
1970 "out float2 TexCoord : TEXCOORD0,\n"
1971 "out float3 EyeVector : TEXCOORD1,\n"
1972 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1973 ")\n"
1974 "{\n"
1975 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
1976 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1977 "       ModelViewProjectionPosition = gl_Position;\n"
1978 "}\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef FRAGMENT_SHADER\n"
1982 "void main\n"
1983 "(\n"
1984 "float2 TexCoord : TEXCOORD0,\n"
1985 "float3 EyeVector : TEXCOORD1,\n"
1986 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
1987 "uniform sampler2D Texture_Normal,\n"
1988 "uniform sampler2D Texture_Refraction,\n"
1989 "uniform sampler2D Texture_Reflection,\n"
1990 "uniform float4 DistortScaleRefractReflect,\n"
1991 "uniform float4 ScreenScaleRefractReflect,\n"
1992 "uniform float4 ScreenCenterRefractReflect,\n"
1993 "uniform float4 RefractColor,\n"
1994 "out float4 gl_FragColor : COLOR\n"
1995 ")\n"
1996 "{\n"
1997 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
1998 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
1999 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2000 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2001 "       // FIXME temporary hack to detect the case that the reflection\n"
2002 "       // gets blackened at edges due to leaving the area that contains actual\n"
2003 "       // content.\n"
2004 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2005 "       // 'appening.\n"
2006 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2007 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2008 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2009 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2010 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2011 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2012 "}\n"
2013 "#endif\n"
2014 "#else // !MODE_REFRACTION\n"
2015 "\n"
2016 "\n"
2017 "\n"
2018 "\n"
2019 "#ifdef MODE_WATER\n"
2020 "#ifdef VERTEX_SHADER\n"
2021 "\n"
2022 "void main\n"
2023 "(\n"
2024 "float4 gl_Vertex : POSITION,\n"
2025 "uniform float4x4 ModelViewProjectionMatrix,\n"
2026 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2027 "uniform float4x4 TexMatrix,\n"
2028 "uniform float3 EyePosition,\n"
2029 "out float4 gl_Position : POSITION,\n"
2030 "out float2 TexCoord : TEXCOORD0,\n"
2031 "out float3 EyeVector : TEXCOORD1,\n"
2032 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2033 ")\n"
2034 "{\n"
2035 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2036 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2037 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2038 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2039 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2040 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2041 "       ModelViewProjectionPosition = gl_Position;\n"
2042 "}\n"
2043 "#endif\n"
2044 "\n"
2045 "#ifdef FRAGMENT_SHADER\n"
2046 "void main\n"
2047 "(\n"
2048 "float2 TexCoord : TEXCOORD0,\n"
2049 "float3 EyeVector : TEXCOORD1,\n"
2050 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2051 "uniform sampler2D Texture_Normal,\n"
2052 "uniform sampler2D Texture_Refraction,\n"
2053 "uniform sampler2D Texture_Reflection,\n"
2054 "uniform float4 DistortScaleRefractReflect,\n"
2055 "uniform float4 ScreenScaleRefractReflect,\n"
2056 "uniform float4 ScreenCenterRefractReflect,\n"
2057 "uniform float4 RefractColor,\n"
2058 "uniform float4 ReflectColor,\n"
2059 "uniform float ReflectFactor,\n"
2060 "uniform float ReflectOffset,\n"
2061 "out float4 gl_FragColor : COLOR\n"
2062 ")\n"
2063 "{\n"
2064 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2065 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2066 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2067 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2068 "       // FIXME temporary hack to detect the case that the reflection\n"
2069 "       // gets blackened at edges due to leaving the area that contains actual\n"
2070 "       // content.\n"
2071 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2072 "       // 'appening.\n"
2073 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2074 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2075 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2076 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2077 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2078 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2079 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2080 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2081 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2082 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2083 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2084 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2085 "}\n"
2086 "#endif\n"
2087 "#else // !MODE_WATER\n"
2088 "\n"
2089 "\n"
2090 "\n"
2091 "\n"
2092 "// 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"
2093 "\n"
2094 "// fragment shader specific:\n"
2095 "#ifdef FRAGMENT_SHADER\n"
2096 "\n"
2097 "#ifdef USEFOG\n"
2098 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2099 "{\n"
2100 "       float fogfrac;\n"
2101 "#ifdef USEFOGOUTSIDE\n"
2102 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2103 "#else\n"
2104 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2105 "#endif\n"
2106 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2107 "}\n"
2108 "#endif\n"
2109 "\n"
2110 "#ifdef USEOFFSETMAPPING\n"
2111 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2112 "{\n"
2113 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2114 "       // 14 sample relief mapping: linear search and then binary search\n"
2115 "       // this basically steps forward a small amount repeatedly until it finds\n"
2116 "       // itself inside solid, then jitters forward and back using decreasing\n"
2117 "       // amounts to find the impact\n"
2118 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2119 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2120 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2121 "       float3 RT = float3(TexCoord, 1);\n"
2122 "       OffsetVector *= 0.1;\n"
2123 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2124 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2125 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2126 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2127 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2128 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2129 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2130 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2131 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2132 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2133 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2134 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2135 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2136 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2137 "       return RT.xy;\n"
2138 "#else\n"
2139 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2140 "       // this basically moves forward the full distance, and then backs up based\n"
2141 "       // on height of samples\n"
2142 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2143 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2144 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2145 "       TexCoord += OffsetVector;\n"
2146 "       OffsetVector *= 0.333;\n"
2147 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2148 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2149 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2150 "       return TexCoord;\n"
2151 "#endif\n"
2152 "}\n"
2153 "#endif // USEOFFSETMAPPING\n"
2154 "\n"
2155 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2156 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2157 "# ifndef USESHADOWMAPVSDCT\n"
2158 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2159 "{\n"
2160 "       float3 adir = abs(dir);\n"
2161 "       float2 tc;\n"
2162 "       float2 offset;\n"
2163 "       float ma;\n"
2164 "       if (adir.x > adir.y)\n"
2165 "       {\n"
2166 "               if (adir.x > adir.z) // X\n"
2167 "               {\n"
2168 "                       ma = adir.x;\n"
2169 "                       tc = dir.zy;\n"
2170 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2171 "               }\n"
2172 "               else // Z\n"
2173 "               {\n"
2174 "                       ma = adir.z;\n"
2175 "                       tc = dir.xy;\n"
2176 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2177 "               }\n"
2178 "       }\n"
2179 "       else\n"
2180 "       {\n"
2181 "               if (adir.y > adir.z) // Y\n"
2182 "               {\n"
2183 "                       ma = adir.y;\n"
2184 "                       tc = dir.xz;\n"
2185 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2186 "               }\n"
2187 "               else // Z\n"
2188 "               {\n"
2189 "                       ma = adir.z;\n"
2190 "                       tc = dir.xy;\n"
2191 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2192 "               }\n"
2193 "       }\n"
2194 "\n"
2195 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2196 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2197 "       stc.z += ShadowMap_Parameters.z;\n"
2198 "       return stc;\n"
2199 "}\n"
2200 "# else\n"
2201 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2202 "{\n"
2203 "       float3 adir = abs(dir);\n"
2204 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2205 "       float ma = max(max(adir.x, adir.y), adir.z);\n"
2206 "       float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2207 "       stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2208 "       stc.z += ShadowMap_Parameters.z;\n"
2209 "       return stc;\n"
2210 "}\n"
2211 "# endif\n"
2212 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2213 "\n"
2214 "#ifdef USESHADOWMAPCUBE\n"
2215 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2216 "{\n"
2217 "    float3 adir = abs(dir);\n"
2218 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2219 "}\n"
2220 "#endif\n"
2221 "\n"
2222 "# ifdef USESHADOWMAPRECT\n"
2223 "#ifdef USESHADOWMAPVSDCT\n"
2224 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2225 "#else\n"
2226 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2227 "#endif\n"
2228 "{\n"
2229 "#ifdef USESHADOWMAPVSDCT\n"
2230 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2231 "#else\n"
2232 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2233 "#endif\n"
2234 "       float f;\n"
2235 "#  ifdef USESHADOWSAMPLER\n"
2236 "\n"
2237 "#    ifdef USESHADOWMAPPCF\n"
2238 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2239 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2240 "#    else\n"
2241 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2242 "#    endif\n"
2243 "\n"
2244 "#  else\n"
2245 "\n"
2246 "#    ifdef USESHADOWMAPPCF\n"
2247 "#      if USESHADOWMAPPCF > 1\n"
2248 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2249 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2250 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2251 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2252 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2253 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2254 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2255 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2256 "#      else\n"
2257 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2258 "    float2 offset = frac(shadowmaptc.xy);\n"
2259 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2260 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2261 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2262 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2263 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2264 "#      endif\n"
2265 "#    else\n"
2266 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2267 "#    endif\n"
2268 "\n"
2269 "#  endif\n"
2270 "       return f;\n"
2271 "}\n"
2272 "# endif\n"
2273 "\n"
2274 "# ifdef USESHADOWMAP2D\n"
2275 "#ifdef USESHADOWMAPVSDCT\n"
2276 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2277 "#else\n"
2278 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2279 "#endif\n"
2280 "{\n"
2281 "#ifdef USESHADOWMAPVSDCT\n"
2282 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2283 "#else\n"
2284 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2285 "#endif\n"
2286 "    float f;\n"
2287 "\n"
2288 "#  ifdef USESHADOWSAMPLER\n"
2289 "#    ifdef USESHADOWMAPPCF\n"
2290 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2291 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2292 "    f = dot(float4(0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2293 "#    else\n"
2294 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2295 "#    endif\n"
2296 "#  else\n"
2297 "#    ifdef USESHADOWMAPPCF\n"
2298 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2299 "#      ifdef GL_ARB_texture_gather\n"
2300 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2301 "#      else\n"
2302 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2303 "#      endif\n"
2304 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2305 "    center *= ShadowMap_TextureScale;\n"
2306 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2307 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2308 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2309 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2310 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2311 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2312 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "#     else\n"
2314 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2315 "#      if USESHADOWMAPPCF > 1\n"
2316 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2317 "    center *= ShadowMap_TextureScale;\n"
2318 "    float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2319 "    float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2320 "    float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2321 "    float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2322 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2323 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2324 "#      else\n"
2325 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2326 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2327 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2328 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2329 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2330 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2331 "#      endif\n"
2332 "#     endif\n"
2333 "#    else\n"
2334 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2335 "#    endif\n"
2336 "#  endif\n"
2337 "    return f;\n"
2338 "}\n"
2339 "# endif\n"
2340 "\n"
2341 "# ifdef USESHADOWMAPCUBE\n"
2342 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2343 "{\n"
2344 "    // apply depth texture cubemap as light filter\n"
2345 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2346 "    float f;\n"
2347 "#  ifdef USESHADOWSAMPLER\n"
2348 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2349 "#  else\n"
2350 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2351 "#  endif\n"
2352 "    return f;\n"
2353 "}\n"
2354 "# endif\n"
2355 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2356 "#endif // FRAGMENT_SHADER\n"
2357 "\n"
2358 "\n"
2359 "\n"
2360 "\n"
2361 "#ifdef MODE_DEFERREDGEOMETRY\n"
2362 "#ifdef VERTEX_SHADER\n"
2363 "void main\n"
2364 "(\n"
2365 "float4 gl_Vertex : POSITION,\n"
2366 "uniform float4x4 ModelViewProjectionMatrix,\n"
2367 "#ifdef USEVERTEXTEXTUREBLEND\n"
2368 "float4 gl_Color : COLOR0,\n"
2369 "#endif\n"
2370 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2371 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2372 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2373 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2374 "uniform float4x4 TexMatrix,\n"
2375 "#ifdef USEVERTEXTEXTUREBLEND\n"
2376 "uniform float4x4 BackgroundTexMatrix,\n"
2377 "#endif\n"
2378 "uniform float4x4 ModelViewMatrix,\n"
2379 "#ifdef USEOFFSETMAPPING\n"
2380 "uniform float3 EyePosition,\n"
2381 "#endif\n"
2382 "out float4 gl_Position : POSITION,\n"
2383 "out float4 gl_FrontColor : COLOR,\n"
2384 "out float4 TexCoordBoth : TEXCOORD0,\n"
2385 "#ifdef USEOFFSETMAPPING\n"
2386 "out float3 EyeVector : TEXCOORD2,\n"
2387 "#endif\n"
2388 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2389 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2390 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2391 ")\n"
2392 "{\n"
2393 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2394 "#ifdef USEVERTEXTEXTUREBLEND\n"
2395 "       gl_FrontColor = gl_Color;\n"
2396 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2397 "#endif\n"
2398 "\n"
2399 "       // transform unnormalized eye direction into tangent space\n"
2400 "#ifdef USEOFFSETMAPPING\n"
2401 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2402 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2403 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2404 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2405 "#endif\n"
2406 "\n"
2407 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2408 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2409 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2410 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2411 "}\n"
2412 "#endif // VERTEX_SHADER\n"
2413 "\n"
2414 "#ifdef FRAGMENT_SHADER\n"
2415 "void main\n"
2416 "(\n"
2417 "float4 TexCoordBoth : TEXCOORD0,\n"
2418 "float3 EyeVector : TEXCOORD2,\n"
2419 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2420 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2421 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2422 "uniform sampler2D Texture_Normal,\n"
2423 "#ifdef USEALPHAKILL\n"
2424 "uniform sampler2D Texture_Color,\n"
2425 "#endif\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 "uniform sampler2D Texture_SecondaryNormal,\n"
2428 "#endif\n"
2429 "#ifdef USEOFFSETMAPPING\n"
2430 "uniform float OffsetMapping_Scale,\n"
2431 "#endif\n"
2432 "uniform half SpecularPower,\n"
2433 "out float4 gl_FragColor : COLOR\n"
2434 ")\n"
2435 "{\n"
2436 "       float2 TexCoord = TexCoordBoth.xy;\n"
2437 "#ifdef USEOFFSETMAPPING\n"
2438 "       // apply offsetmapping\n"
2439 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2440 "#define TexCoord TexCoordOffset\n"
2441 "#endif\n"
2442 "\n"
2443 "#ifdef USEALPHAKILL\n"
2444 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2445 "               discard;\n"
2446 "#endif\n"
2447 "\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2450 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2451 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2452 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2453 "#endif\n"
2454 "\n"
2455 "#ifdef USEVERTEXTEXTUREBLEND\n"
2456 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2457 "#else\n"
2458 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2459 "#endif\n"
2460 "\n"
2461 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2462 "}\n"
2463 "#endif // FRAGMENT_SHADER\n"
2464 "#else // !MODE_DEFERREDGEOMETRY\n"
2465 "\n"
2466 "\n"
2467 "\n"
2468 "\n"
2469 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2470 "#ifdef VERTEX_SHADER\n"
2471 "void main\n"
2472 "(\n"
2473 "float4 gl_Vertex : POSITION,\n"
2474 "uniform float4x4 ModelViewProjectionMatrix,\n"
2475 "uniform float4x4 ModelViewMatrix,\n"
2476 "out float4 gl_Position : POSITION,\n"
2477 "out float4 ModelViewPosition : TEXCOORD0\n"
2478 ")\n"
2479 "{\n"
2480 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2481 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2482 "}\n"
2483 "#endif // VERTEX_SHADER\n"
2484 "\n"
2485 "#ifdef FRAGMENT_SHADER\n"
2486 "void main\n"
2487 "(\n"
2488 "float2 Pixel : WPOS,\n"
2489 "float4 ModelViewPosition : TEXCOORD0,\n"
2490 "uniform float4x4 ViewToLight,\n"
2491 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2492 "uniform float3 LightPosition,\n"
2493 "uniform half2 PixelToScreenTexCoord,\n"
2494 "uniform half3 DeferredColor_Ambient,\n"
2495 "uniform half3 DeferredColor_Diffuse,\n"
2496 "#ifdef USESPECULAR\n"
2497 "uniform half3 DeferredColor_Specular,\n"
2498 "uniform half SpecularPower,\n"
2499 "#endif\n"
2500 "uniform sampler2D Texture_Attenuation,\n"
2501 "uniform sampler2D Texture_ScreenDepth,\n"
2502 "uniform sampler2D Texture_ScreenNormalMap,\n"
2503 "\n"
2504 "#ifdef USESHADOWMAPRECT\n"
2505 "# ifdef USESHADOWSAMPLER\n"
2506 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2507 "# else\n"
2508 "uniform samplerRECT Texture_ShadowMapRect,\n"
2509 "# endif\n"
2510 "#endif\n"
2511 "\n"
2512 "#ifdef USESHADOWMAP2D\n"
2513 "# ifdef USESHADOWSAMPLER\n"
2514 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2515 "# else\n"
2516 "uniform sampler2D Texture_ShadowMap2D,\n"
2517 "# endif\n"
2518 "#endif\n"
2519 "\n"
2520 "#ifdef USESHADOWMAPVSDCT\n"
2521 "uniform samplerCUBE Texture_CubeProjection,\n"
2522 "#endif\n"
2523 "\n"
2524 "#ifdef USESHADOWMAPCUBE\n"
2525 "# ifdef USESHADOWSAMPLER\n"
2526 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2527 "# else\n"
2528 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2529 "# endif\n"
2530 "#endif\n"
2531 "\n"
2532 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2533 "uniform float2 ShadowMap_TextureScale,\n"
2534 "uniform float4 ShadowMap_Parameters,\n"
2535 "#endif\n"
2536 "\n"
2537 "out float4 gl_FragData0 : COLOR0,\n"
2538 "out float4 gl_FragData1 : COLOR1\n"
2539 ")\n"
2540 "{\n"
2541 "       // calculate viewspace pixel position\n"
2542 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2543 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2544 "       float3 position;\n"
2545 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2546 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2547 "       // decode viewspace pixel normal\n"
2548 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2549 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2550 "       // surfacenormal = pixel normal in viewspace\n"
2551 "       // LightVector = pixel to light in viewspace\n"
2552 "       // CubeVector = position in lightspace\n"
2553 "       // eyevector = pixel to view in viewspace\n"
2554 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2555 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2556 "#ifdef USEDIFFUSE\n"
2557 "       // calculate diffuse shading\n"
2558 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2559 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2560 "#endif\n"
2561 "#ifdef USESPECULAR\n"
2562 "       // calculate directional shading\n"
2563 "       float3 eyevector = position * -1.0;\n"
2564 "#  ifdef USEEXACTSPECULARMATH\n"
2565 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower);\n"
2566 "#  else\n"
2567 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2568 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2569 "#  endif\n"
2570 "#endif\n"
2571 "\n"
2572 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2573 "       fade *= ShadowMapCompare(CubeVector,\n"
2574 "# if defined(USESHADOWMAP2D)\n"
2575 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2576 "# endif\n"
2577 "# if defined(USESHADOWMAPRECT)\n"
2578 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2579 "# endif\n"
2580 "# if defined(USESHADOWMAPCUBE)\n"
2581 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2582 "# endif\n"
2583 "\n"
2584 "#ifdef USESHADOWMAPVSDCT\n"
2585 ", Texture_CubeProjection\n"
2586 "#endif\n"
2587 "       );\n"
2588 "#endif\n"
2589 "\n"
2590 "#ifdef USEDIFFUSE\n"
2591 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2592 "#else\n"
2593 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2594 "#endif\n"
2595 "#ifdef USESPECULAR\n"
2596 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2597 "#else\n"
2598 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2599 "#endif\n"
2600 "\n"
2601 "# ifdef USECUBEFILTER\n"
2602 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2603 "       gl_FragData0.rgb *= cubecolor;\n"
2604 "       gl_FragData1.rgb *= cubecolor;\n"
2605 "# endif\n"
2606 "}\n"
2607 "#endif // FRAGMENT_SHADER\n"
2608 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2609 "\n"
2610 "\n"
2611 "\n"
2612 "\n"
2613 "#ifdef VERTEX_SHADER\n"
2614 "void main\n"
2615 "(\n"
2616 "float4 gl_Vertex : POSITION,\n"
2617 "uniform float4x4 ModelViewProjectionMatrix,\n"
2618 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2619 "float4 gl_Color : COLOR0,\n"
2620 "#endif\n"
2621 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2622 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2623 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2624 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2625 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2626 "\n"
2627 "uniform float3 EyePosition,\n"
2628 "uniform float4x4 TexMatrix,\n"
2629 "#ifdef USEVERTEXTEXTUREBLEND\n"
2630 "uniform float4x4 BackgroundTexMatrix,\n"
2631 "#endif\n"
2632 "#ifdef MODE_LIGHTSOURCE\n"
2633 "uniform float4x4 ModelToLight,\n"
2634 "#endif\n"
2635 "#ifdef MODE_LIGHTSOURCE\n"
2636 "uniform float3 LightPosition,\n"
2637 "#endif\n"
2638 "#ifdef MODE_LIGHTDIRECTION\n"
2639 "uniform float3 LightDir,\n"
2640 "#endif\n"
2641 "uniform float4 FogPlane,\n"
2642 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2643 "uniform float3 LightPosition,\n"
2644 "#endif\n"
2645 "\n"
2646 "out float4 gl_FrontColor : COLOR,\n"
2647 "out float4 TexCoordBoth : TEXCOORD0,\n"
2648 "#ifdef USELIGHTMAP\n"
2649 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2650 "#endif\n"
2651 "#ifdef USEEYEVECTOR\n"
2652 "out float3 EyeVector : TEXCOORD2,\n"
2653 "#endif\n"
2654 "#ifdef USEREFLECTION\n"
2655 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2656 "#endif\n"
2657 "#ifdef USEFOG\n"
2658 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2659 "#endif\n"
2660 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2661 "out float3 LightVector : TEXCOORD5,\n"
2662 "#endif\n"
2663 "#ifdef MODE_LIGHTSOURCE\n"
2664 "out float3 CubeVector : TEXCOORD3,\n"
2665 "#endif\n"
2666 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2667 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2668 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2669 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2670 "#endif\n"
2671 "out float4 gl_Position : POSITION\n"
2672 ")\n"
2673 "{\n"
2674 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2675 "       gl_FrontColor = gl_Color;\n"
2676 "#endif\n"
2677 "       // copy the surface texcoord\n"
2678 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2679 "#ifdef USEVERTEXTEXTUREBLEND\n"
2680 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2681 "#endif\n"
2682 "#ifdef USELIGHTMAP\n"
2683 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef MODE_LIGHTSOURCE\n"
2687 "       // transform vertex position into light attenuation/cubemap space\n"
2688 "       // (-1 to +1 across the light box)\n"
2689 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2690 "\n"
2691 "# ifdef USEDIFFUSE\n"
2692 "       // transform unnormalized light direction into tangent space\n"
2693 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2694 "       //  normalize it per pixel)\n"
2695 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2696 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2697 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2698 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2699 "# endif\n"
2700 "#endif\n"
2701 "\n"
2702 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2703 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2704 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2705 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2706 "#endif\n"
2707 "\n"
2708 "       // transform unnormalized eye direction into tangent space\n"
2709 "#ifdef USEEYEVECTOR\n"
2710 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2711 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2712 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2713 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEFOG\n"
2717 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2718 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2719 "#endif\n"
2720 "\n"
2721 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2722 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2723 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2724 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2725 "#endif\n"
2726 "\n"
2727 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2728 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2729 "\n"
2730 "#ifdef USEREFLECTION\n"
2731 "       ModelViewProjectionPosition = gl_Position;\n"
2732 "#endif\n"
2733 "}\n"
2734 "#endif // VERTEX_SHADER\n"
2735 "\n"
2736 "\n"
2737 "\n"
2738 "\n"
2739 "#ifdef FRAGMENT_SHADER\n"
2740 "void main\n"
2741 "(\n"
2742 "#ifdef USEDEFERREDLIGHTMAP\n"
2743 "float2 Pixel : WPOS,\n"
2744 "#endif\n"
2745 "float4 gl_FrontColor : COLOR,\n"
2746 "float4 TexCoordBoth : TEXCOORD0,\n"
2747 "#ifdef USELIGHTMAP\n"
2748 "float2 TexCoordLightmap : TEXCOORD1,\n"
2749 "#endif\n"
2750 "#ifdef USEEYEVECTOR\n"
2751 "float3 EyeVector : TEXCOORD2,\n"
2752 "#endif\n"
2753 "#ifdef USEREFLECTION\n"
2754 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2755 "#endif\n"
2756 "#ifdef USEFOG\n"
2757 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2758 "#endif\n"
2759 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2760 "float3 LightVector : TEXCOORD5,\n"
2761 "#endif\n"
2762 "#ifdef MODE_LIGHTSOURCE\n"
2763 "float3 CubeVector : TEXCOORD3,\n"
2764 "#endif\n"
2765 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2766 "float4 ModelViewPosition : TEXCOORD0,\n"
2767 "#endif\n"
2768 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY)\n"
2769 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2770 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2771 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2772 "#endif\n"
2773 "\n"
2774 "uniform sampler2D Texture_Normal,\n"
2775 "uniform sampler2D Texture_Color,\n"
2776 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2777 "uniform sampler2D Texture_Gloss,\n"
2778 "#endif\n"
2779 "#ifdef USEGLOW\n"
2780 "uniform sampler2D Texture_Glow,\n"
2781 "#endif\n"
2782 "#ifdef USEVERTEXTEXTUREBLEND\n"
2783 "uniform sampler2D Texture_SecondaryNormal,\n"
2784 "uniform sampler2D Texture_SecondaryColor,\n"
2785 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2786 "uniform sampler2D Texture_SecondaryGloss,\n"
2787 "#endif\n"
2788 "#ifdef USEGLOW\n"
2789 "uniform sampler2D Texture_SecondaryGlow,\n"
2790 "#endif\n"
2791 "#endif\n"
2792 "#ifdef USECOLORMAPPING\n"
2793 "uniform sampler2D Texture_Pants,\n"
2794 "uniform sampler2D Texture_Shirt,\n"
2795 "#endif\n"
2796 "#ifdef USEFOG\n"
2797 "uniform sampler2D Texture_FogMask,\n"
2798 "#endif\n"
2799 "#ifdef USELIGHTMAP\n"
2800 "uniform sampler2D Texture_Lightmap,\n"
2801 "#endif\n"
2802 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2803 "uniform sampler2D Texture_Deluxemap,\n"
2804 "#endif\n"
2805 "#ifdef USEREFLECTION\n"
2806 "uniform sampler2D Texture_Reflection,\n"
2807 "#endif\n"
2808 "\n"
2809 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2810 "uniform sampler2D Texture_ScreenDepth,\n"
2811 "uniform sampler2D Texture_ScreenNormalMap,\n"
2812 "#endif\n"
2813 "#ifdef USEDEFERREDLIGHTMAP\n"
2814 "uniform sampler2D Texture_ScreenDiffuse,\n"
2815 "uniform sampler2D Texture_ScreenSpecular,\n"
2816 "#endif\n"
2817 "\n"
2818 "#ifdef USECOLORMAPPING\n"
2819 "uniform half3 Color_Pants,\n"
2820 "uniform half3 Color_Shirt,\n"
2821 "#endif\n"
2822 "#ifdef USEFOG\n"
2823 "uniform float3 FogColor,\n"
2824 "uniform float FogRangeRecip,\n"
2825 "uniform float FogPlaneViewDist,\n"
2826 "uniform float FogHeightFade,\n"
2827 "#endif\n"
2828 "\n"
2829 "#ifdef USEOFFSETMAPPING\n"
2830 "uniform float OffsetMapping_Scale,\n"
2831 "#endif\n"
2832 "\n"
2833 "#ifdef USEDEFERREDLIGHTMAP\n"
2834 "uniform half2 PixelToScreenTexCoord,\n"
2835 "uniform half3 DeferredMod_Diffuse,\n"
2836 "uniform half3 DeferredMod_Specular,\n"
2837 "#endif\n"
2838 "uniform half3 Color_Ambient,\n"
2839 "uniform half3 Color_Diffuse,\n"
2840 "uniform half3 Color_Specular,\n"
2841 "uniform half SpecularPower,\n"
2842 "#ifdef USEGLOW\n"
2843 "uniform half3 Color_Glow,\n"
2844 "#endif\n"
2845 "uniform half Alpha,\n"
2846 "#ifdef USEREFLECTION\n"
2847 "uniform float4 DistortScaleRefractReflect,\n"
2848 "uniform float4 ScreenScaleRefractReflect,\n"
2849 "uniform float4 ScreenCenterRefractReflect,\n"
2850 "uniform half4 ReflectColor,\n"
2851 "#endif\n"
2852 "#ifdef MODE_LIGHTDIRECTION\n"
2853 "uniform half3 LightColor,\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTSOURCE\n"
2856 "uniform half3 LightColor,\n"
2857 "#endif\n"
2858 "\n"
2859 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2860 "uniform sampler2D Texture_Attenuation,\n"
2861 "uniform samplerCUBE Texture_Cube,\n"
2862 "\n"
2863 "#ifdef USESHADOWMAPRECT\n"
2864 "# ifdef USESHADOWSAMPLER\n"
2865 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2866 "# else\n"
2867 "uniform samplerRECT Texture_ShadowMapRect,\n"
2868 "# endif\n"
2869 "#endif\n"
2870 "\n"
2871 "#ifdef USESHADOWMAP2D\n"
2872 "# ifdef USESHADOWSAMPLER\n"
2873 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2874 "# else\n"
2875 "uniform sampler2D Texture_ShadowMap2D,\n"
2876 "# endif\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USESHADOWMAPVSDCT\n"
2880 "uniform samplerCUBE Texture_CubeProjection,\n"
2881 "#endif\n"
2882 "\n"
2883 "#ifdef USESHADOWMAPCUBE\n"
2884 "# ifdef USESHADOWSAMPLER\n"
2885 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2886 "# else\n"
2887 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2888 "# endif\n"
2889 "#endif\n"
2890 "\n"
2891 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2892 "uniform float2 ShadowMap_TextureScale,\n"
2893 "uniform float4 ShadowMap_Parameters,\n"
2894 "#endif\n"
2895 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2896 "\n"
2897 "out float4 gl_FragColor : COLOR\n"
2898 ")\n"
2899 "{\n"
2900 "       float2 TexCoord = TexCoordBoth.xy;\n"
2901 "#ifdef USEVERTEXTEXTUREBLEND\n"
2902 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2903 "#endif\n"
2904 "#ifdef USEOFFSETMAPPING\n"
2905 "       // apply offsetmapping\n"
2906 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2907 "#define TexCoord TexCoordOffset\n"
2908 "#endif\n"
2909 "\n"
2910 "       // combine the diffuse textures (base, pants, shirt)\n"
2911 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2912 "#ifdef USEALPHAKILL\n"
2913 "       if (color.a < 0.5)\n"
2914 "               discard;\n"
2915 "#endif\n"
2916 "       color.a *= Alpha;\n"
2917 "#ifdef USECOLORMAPPING\n"
2918 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2919 "#endif\n"
2920 "#ifdef USEVERTEXTEXTUREBLEND\n"
2921 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2922 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2923 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2924 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2925 "       color.a = 1.0;\n"
2926 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2927 "#endif\n"
2928 "\n"
2929 "       // get the surface normal\n"
2930 "#ifdef USEVERTEXTEXTUREBLEND\n"
2931 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2932 "#else\n"
2933 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2934 "#endif\n"
2935 "\n"
2936 "       // get the material colors\n"
2937 "       half3 diffusetex = color.rgb;\n"
2938 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2939 "# ifdef USEVERTEXTEXTUREBLEND\n"
2940 "       half3 glosstex = half3(lerp(float3(tex2D(Texture_SecondaryGloss, TexCoord2)), float3(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2941 "# else\n"
2942 "       half3 glosstex = half3(tex2D(Texture_Gloss, TexCoord));\n"
2943 "# endif\n"
2944 "#endif\n"
2945 "\n"
2946 "\n"
2947 "\n"
2948 "\n"
2949 "#ifdef MODE_LIGHTSOURCE\n"
2950 "       // light source\n"
2951 "#ifdef USEDIFFUSE\n"
2952 "       half3 lightnormal = half3(normalize(LightVector));\n"
2953 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2954 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2955 "#ifdef USESPECULAR\n"
2956 "#ifdef USEEXACTSPECULARMATH\n"
2957 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
2958 "#else\n"
2959 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2960 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
2961 "#endif\n"
2962 "       color.rgb += glosstex * (specular * Color_Specular);\n"
2963 "#endif\n"
2964 "#else\n"
2965 "       color.rgb = diffusetex * Color_Ambient;\n"
2966 "#endif\n"
2967 "       color.rgb *= LightColor;\n"
2968 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2969 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
2970 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
2971 "# if defined(USESHADOWMAP2D)\n"
2972 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2973 "# endif\n"
2974 "# if defined(USESHADOWMAPRECT)\n"
2975 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2976 "# endif\n"
2977 "# if defined(USESHADOWMAPCUBE)\n"
2978 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2979 "# endif\n"
2980 "\n"
2981 "#ifdef USESHADOWMAPVSDCT\n"
2982 ", Texture_CubeProjection\n"
2983 "#endif\n"
2984 "       );\n"
2985 "\n"
2986 "#endif\n"
2987 "# ifdef USECUBEFILTER\n"
2988 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
2989 "# endif\n"
2990 "#endif // MODE_LIGHTSOURCE\n"
2991 "\n"
2992 "\n"
2993 "\n"
2994 "\n"
2995 "#ifdef MODE_LIGHTDIRECTION\n"
2996 "#define SHADING\n"
2997 "#ifdef USEDIFFUSE\n"
2998 "       half3 lightnormal = half3(normalize(LightVector));\n"
2999 "#endif\n"
3000 "#define lightcolor LightColor\n"
3001 "#endif // MODE_LIGHTDIRECTION\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "#define SHADING\n"
3004 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3005 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3006 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3007 "       // convert modelspace light vector to tangentspace\n"
3008 "       half3 lightnormal;\n"
3009 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3010 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3011 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3012 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3013 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3014 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3015 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3016 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3017 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3018 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3019 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3020 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3021 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3022 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3023 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3024 "#define SHADING\n"
3025 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3026 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3027 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3028 "#endif\n"
3029 "\n"
3030 "\n"
3031 "\n"
3032 "\n"
3033 "#ifdef MODE_LIGHTMAP\n"
3034 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3035 "#endif // MODE_LIGHTMAP\n"
3036 "#ifdef MODE_VERTEXCOLOR\n"
3037 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3038 "#endif // MODE_VERTEXCOLOR\n"
3039 "#ifdef MODE_FLATCOLOR\n"
3040 "       color.rgb = diffusetex * Color_Ambient;\n"
3041 "#endif // MODE_FLATCOLOR\n"
3042 "\n"
3043 "\n"
3044 "\n"
3045 "\n"
3046 "#ifdef SHADING\n"
3047 "# ifdef USEDIFFUSE\n"
3048 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3049 "#  ifdef USESPECULAR\n"
3050 "#   ifdef USEEXACTSPECULARMATH\n"
3051 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower);\n"
3052 "#   else\n"
3053 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3054 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower);\n"
3055 "#   endif\n"
3056 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex * Color_Specular * specular) * lightcolor;\n"
3057 "#  else\n"
3058 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3059 "#  endif\n"
3060 "# else\n"
3061 "       color.rgb = diffusetex * Color_Ambient;\n"
3062 "# endif\n"
3063 "#endif\n"
3064 "\n"
3065 "#ifdef USEDEFERREDLIGHTMAP\n"
3066 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3067 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3068 "       color.rgb += glosstex * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3069 "#endif\n"
3070 "\n"
3071 "#ifdef USEGLOW\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3074 "#else\n"
3075 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3076 "#endif\n"
3077 "#endif\n"
3078 "\n"
3079 "#ifdef USEFOG\n"
3080 "#ifdef MODE_LIGHTSOURCE\n"
3081 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3082 "#else\n"
3083 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3084 "#endif\n"
3085 "#endif\n"
3086 "\n"
3087 "       // 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"
3088 "#ifdef USEREFLECTION\n"
3089 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3090 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3091 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3092 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3093 "       // FIXME temporary hack to detect the case that the reflection\n"
3094 "       // gets blackened at edges due to leaving the area that contains actual\n"
3095 "       // content.\n"
3096 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3097 "       // 'appening.\n"
3098 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3099 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3100 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3101 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3102 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3103 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3104 "#endif\n"
3105 "\n"
3106 "       gl_FragColor = float4(color);\n"
3107 "}\n"
3108 "#endif // FRAGMENT_SHADER\n"
3109 "\n"
3110 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3111 "#endif // !MODE_DEFERREDGEOMETRY\n"
3112 "#endif // !MODE_WATER\n"
3113 "#endif // !MODE_REFRACTION\n"
3114 "#endif // !MODE_BLOOMBLUR\n"
3115 "#endif // !MODE_GENERIC\n"
3116 "#endif // !MODE_POSTPROCESS\n"
3117 "#endif // !MODE_SHOWDEPTH\n"
3118 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3119 ;
3120
3121 //=======================================================================================================================================================
3122
3123 typedef struct shaderpermutationinfo_s
3124 {
3125         const char *pretext;
3126         const char *name;
3127 }
3128 shaderpermutationinfo_t;
3129
3130 typedef struct shadermodeinfo_s
3131 {
3132         const char *vertexfilename;
3133         const char *geometryfilename;
3134         const char *fragmentfilename;
3135         const char *pretext;
3136         const char *name;
3137 }
3138 shadermodeinfo_t;
3139
3140 typedef enum shaderpermutation_e
3141 {
3142         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3143         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3144         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3145         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3146         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3147         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3148         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3149         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3150         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3151         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3152         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3153         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3154         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3155         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3156         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3157         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3158         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3159         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3160         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3161         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3162         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3163         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3164         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3165         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3166         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3167         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3168         SHADERPERMUTATION_LIMIT = 1<<26, ///< size of permutations array
3169         SHADERPERMUTATION_COUNT = 26 ///< size of shaderpermutationinfo array
3170 }
3171 shaderpermutation_t;
3172
3173 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3174 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3175 {
3176         {"#define USEDIFFUSE\n", " diffuse"},
3177         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3178         {"#define USEVIEWTINT\n", " viewtint"},
3179         {"#define USECOLORMAPPING\n", " colormapping"},
3180         {"#define USESATURATION\n", " saturation"},
3181         {"#define USEFOGINSIDE\n", " foginside"},
3182         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3183         {"#define USEGAMMARAMPS\n", " gammaramps"},
3184         {"#define USECUBEFILTER\n", " cubefilter"},
3185         {"#define USEGLOW\n", " glow"},
3186         {"#define USEBLOOM\n", " bloom"},
3187         {"#define USESPECULAR\n", " specular"},
3188         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3189         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3190         {"#define USEREFLECTION\n", " reflection"},
3191         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3192         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3193         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3194         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3195         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3196         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3197         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3198         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3199         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3200         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3201         {"#define USEALPHAKILL\n", " alphakill"},
3202 };
3203
3204 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3205 typedef enum shadermode_e
3206 {
3207         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3208         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3209         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3210         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3211         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3212         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3213         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3214         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3215         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3216         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3217         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3218         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3219         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3220         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3221         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3222         SHADERMODE_COUNT
3223 }
3224 shadermode_t;
3225
3226 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3227 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3228 {
3229         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3230         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3231         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3232         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3233         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3234         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3235         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3236         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3237         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3238         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3239         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3240         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3241         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3242         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3243         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3244 };
3245
3246 #ifdef SUPPORTCG
3247 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3248 {
3249         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3250         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3251         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3252         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3253         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3254         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3255         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3256         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3257         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3258         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3259         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3260         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3261         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3262         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3263         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3264 };
3265 #endif
3266
3267 struct r_glsl_permutation_s;
3268 typedef struct r_glsl_permutation_s
3269 {
3270         /// hash lookup data
3271         struct r_glsl_permutation_s *hashnext;
3272         unsigned int mode;
3273         unsigned int permutation;
3274
3275         /// indicates if we have tried compiling this permutation already
3276         qboolean compiled;
3277         /// 0 if compilation failed
3278         int program;
3279         /// locations of detected uniforms in program object, or -1 if not found
3280         int loc_Texture_First;
3281         int loc_Texture_Second;
3282         int loc_Texture_GammaRamps;
3283         int loc_Texture_Normal;
3284         int loc_Texture_Color;
3285         int loc_Texture_Gloss;
3286         int loc_Texture_Glow;
3287         int loc_Texture_SecondaryNormal;
3288         int loc_Texture_SecondaryColor;
3289         int loc_Texture_SecondaryGloss;
3290         int loc_Texture_SecondaryGlow;
3291         int loc_Texture_Pants;
3292         int loc_Texture_Shirt;
3293         int loc_Texture_FogMask;
3294         int loc_Texture_Lightmap;
3295         int loc_Texture_Deluxemap;
3296         int loc_Texture_Attenuation;
3297         int loc_Texture_Cube;
3298         int loc_Texture_Refraction;
3299         int loc_Texture_Reflection;
3300         int loc_Texture_ShadowMapRect;
3301         int loc_Texture_ShadowMapCube;
3302         int loc_Texture_ShadowMap2D;
3303         int loc_Texture_CubeProjection;
3304         int loc_Texture_ScreenDepth;
3305         int loc_Texture_ScreenNormalMap;
3306         int loc_Texture_ScreenDiffuse;
3307         int loc_Texture_ScreenSpecular;
3308         int loc_Alpha;
3309         int loc_BloomBlur_Parameters;
3310         int loc_ClientTime;
3311         int loc_Color_Ambient;
3312         int loc_Color_Diffuse;
3313         int loc_Color_Specular;
3314         int loc_Color_Glow;
3315         int loc_Color_Pants;
3316         int loc_Color_Shirt;
3317         int loc_DeferredColor_Ambient;
3318         int loc_DeferredColor_Diffuse;
3319         int loc_DeferredColor_Specular;
3320         int loc_DeferredMod_Diffuse;
3321         int loc_DeferredMod_Specular;
3322         int loc_DistortScaleRefractReflect;
3323         int loc_EyePosition;
3324         int loc_FogColor;
3325         int loc_FogHeightFade;
3326         int loc_FogPlane;
3327         int loc_FogPlaneViewDist;
3328         int loc_FogRangeRecip;
3329         int loc_LightColor;
3330         int loc_LightDir;
3331         int loc_LightPosition;
3332         int loc_OffsetMapping_Scale;
3333         int loc_PixelSize;
3334         int loc_ReflectColor;
3335         int loc_ReflectFactor;
3336         int loc_ReflectOffset;
3337         int loc_RefractColor;
3338         int loc_Saturation;
3339         int loc_ScreenCenterRefractReflect;
3340         int loc_ScreenScaleRefractReflect;
3341         int loc_ScreenToDepth;
3342         int loc_ShadowMap_Parameters;
3343         int loc_ShadowMap_TextureScale;
3344         int loc_SpecularPower;
3345         int loc_UserVec1;
3346         int loc_UserVec2;
3347         int loc_UserVec3;
3348         int loc_UserVec4;
3349         int loc_ViewTintColor;
3350         int loc_ViewToLight;
3351         int loc_ModelToLight;
3352         int loc_TexMatrix;
3353         int loc_BackgroundTexMatrix;
3354         int loc_ModelViewProjectionMatrix;
3355         int loc_ModelViewMatrix;
3356         int loc_PixelToScreenTexCoord;
3357 }
3358 r_glsl_permutation_t;
3359
3360 #define SHADERPERMUTATION_HASHSIZE 256
3361
3362 /// information about each possible shader permutation
3363 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3364 /// currently selected permutation
3365 r_glsl_permutation_t *r_glsl_permutation;
3366 /// storage for permutations linked in the hash table
3367 memexpandablearray_t r_glsl_permutationarray;
3368
3369 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3370 {
3371         //unsigned int hashdepth = 0;
3372         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3373         r_glsl_permutation_t *p;
3374         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3375         {
3376                 if (p->mode == mode && p->permutation == permutation)
3377                 {
3378                         //if (hashdepth > 10)
3379                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3380                         return p;
3381                 }
3382                 //hashdepth++;
3383         }
3384         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3385         p->mode = mode;
3386         p->permutation = permutation;
3387         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3388         r_glsl_permutationhash[mode][hashindex] = p;
3389         //if (hashdepth > 10)
3390         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3391         return p;
3392 }
3393
3394 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3395 {
3396         char *shaderstring;
3397         if (!filename || !filename[0])
3398                 return NULL;
3399         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3400         if (shaderstring)
3401         {
3402                 if (printfromdisknotice)
3403                         Con_DPrintf("from disk %s... ", filename);
3404                 return shaderstring;
3405         }
3406         else if (!strcmp(filename, "glsl/default.glsl"))
3407         {
3408                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtinshaderstring) + 1);
3409                 memcpy(shaderstring, builtinshaderstring, strlen(builtinshaderstring) + 1);
3410         }
3411         return shaderstring;
3412 }
3413
3414 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3415 {
3416         int i;
3417         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3418         int vertstrings_count = 0;
3419         int geomstrings_count = 0;
3420         int fragstrings_count = 0;
3421         char *vertexstring, *geometrystring, *fragmentstring;
3422         const char *vertstrings_list[32+3];
3423         const char *geomstrings_list[32+3];
3424         const char *fragstrings_list[32+3];
3425         char permutationname[256];
3426
3427         if (p->compiled)
3428                 return;
3429         p->compiled = true;
3430         p->program = 0;
3431
3432         permutationname[0] = 0;
3433         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3434         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3435         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3436
3437         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3438
3439         // the first pretext is which type of shader to compile as
3440         // (later these will all be bound together as a program object)
3441         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3442         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3443         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3444
3445         // the second pretext is the mode (for example a light source)
3446         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3447         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3448         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3449         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3450
3451         // now add all the permutation pretexts
3452         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3453         {
3454                 if (permutation & (1<<i))
3455                 {
3456                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3457                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3458                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3459                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3460                 }
3461                 else
3462                 {
3463                         // keep line numbers correct
3464                         vertstrings_list[vertstrings_count++] = "\n";
3465                         geomstrings_list[geomstrings_count++] = "\n";
3466                         fragstrings_list[fragstrings_count++] = "\n";
3467                 }
3468         }
3469
3470         // now append the shader text itself
3471         vertstrings_list[vertstrings_count++] = vertexstring;
3472         geomstrings_list[geomstrings_count++] = geometrystring;
3473         fragstrings_list[fragstrings_count++] = fragmentstring;
3474
3475         // if any sources were NULL, clear the respective list
3476         if (!vertexstring)
3477                 vertstrings_count = 0;
3478         if (!geometrystring)
3479                 geomstrings_count = 0;
3480         if (!fragmentstring)
3481                 fragstrings_count = 0;
3482
3483         // compile the shader program
3484         if (vertstrings_count + geomstrings_count + fragstrings_count)
3485                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3486         if (p->program)
3487         {
3488                 CHECKGLERROR
3489                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3490                 // look up all the uniform variable names we care about, so we don't
3491                 // have to look them up every time we set them
3492
3493                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3494                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3495                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3496                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3497                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3498                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3499                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3500                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3501                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3502                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3503                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3504                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3505                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3506                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3507                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3508                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3509                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3510                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3511                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3512                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3513                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3514                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3515                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3516                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3517                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3518                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3519                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3520                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3521                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3522                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3523                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3524                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3525                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3526                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3527                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3528                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3529                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3530                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3531                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3532                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3533                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3534                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3535                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3536                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3537                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3538                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3539                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3540                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3541                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3542                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3543                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3544                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3545                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3546                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3547                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3548                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3549                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3550                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3551                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3552                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3553                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3554                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3555                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3556                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3557                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3558                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3559                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3560                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3561                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3562                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3563                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3564                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3565                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3566                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3567                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3568                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3569                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3570                 // initialize the samplers to refer to the texture units we use
3571                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3572                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3573                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3574                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3575                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3576                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3577                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3578                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3579                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3580                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3581                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3582                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3583                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3584                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3585                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3586                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3587                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3588                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3589                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3590                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3591                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3592                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3593                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3594                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3595                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3596                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3597                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3598                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3599                 CHECKGLERROR
3600                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3601         }
3602         else
3603                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3604
3605         // free the strings
3606         if (vertexstring)
3607                 Mem_Free(vertexstring);
3608         if (geometrystring)
3609                 Mem_Free(geometrystring);
3610         if (fragmentstring)
3611                 Mem_Free(fragmentstring);
3612 }
3613
3614 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3615 {
3616         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3617         if (r_glsl_permutation != perm)
3618         {
3619                 r_glsl_permutation = perm;
3620                 if (!r_glsl_permutation->program)
3621                 {
3622                         if (!r_glsl_permutation->compiled)
3623                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3624                         if (!r_glsl_permutation->program)
3625                         {
3626                                 // remove features until we find a valid permutation
3627                                 int i;
3628                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3629                                 {
3630                                         // reduce i more quickly whenever it would not remove any bits
3631                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3632                                         if (!(permutation & j))
3633                                                 continue;
3634                                         permutation -= j;
3635                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3636                                         if (!r_glsl_permutation->compiled)
3637                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3638                                         if (r_glsl_permutation->program)
3639                                                 break;
3640                                 }
3641                                 if (i >= SHADERPERMUTATION_COUNT)
3642                                 {
3643                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3644                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3645                                         qglUseProgramObjectARB(0);CHECKGLERROR
3646                                         return; // no bit left to clear, entire mode is broken
3647                                 }
3648                         }
3649                 }
3650                 CHECKGLERROR
3651                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3652         }
3653         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3654         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3655 }
3656
3657 #ifdef SUPPORTCG
3658 #include <Cg/cgGL.h>
3659 struct r_cg_permutation_s;
3660 typedef struct r_cg_permutation_s
3661 {
3662         /// hash lookup data
3663         struct r_cg_permutation_s *hashnext;
3664         unsigned int mode;
3665         unsigned int permutation;
3666
3667         /// indicates if we have tried compiling this permutation already
3668         qboolean compiled;
3669         /// 0 if compilation failed
3670         CGprogram vprogram;
3671         CGprogram fprogram;
3672         /// locations of detected parameters in programs, or NULL if not found
3673         CGparameter vp_EyePosition;
3674         CGparameter vp_FogPlane;
3675         CGparameter vp_LightDir;
3676         CGparameter vp_LightPosition;
3677         CGparameter vp_ModelToLight;
3678         CGparameter vp_TexMatrix;
3679         CGparameter vp_BackgroundTexMatrix;
3680         CGparameter vp_ModelViewProjectionMatrix;
3681         CGparameter vp_ModelViewMatrix;
3682
3683         CGparameter fp_Texture_First;
3684         CGparameter fp_Texture_Second;
3685         CGparameter fp_Texture_GammaRamps;
3686         CGparameter fp_Texture_Normal;
3687         CGparameter fp_Texture_Color;
3688         CGparameter fp_Texture_Gloss;
3689         CGparameter fp_Texture_Glow;
3690         CGparameter fp_Texture_SecondaryNormal;
3691         CGparameter fp_Texture_SecondaryColor;
3692         CGparameter fp_Texture_SecondaryGloss;
3693         CGparameter fp_Texture_SecondaryGlow;
3694         CGparameter fp_Texture_Pants;
3695         CGparameter fp_Texture_Shirt;
3696         CGparameter fp_Texture_FogMask;
3697         CGparameter fp_Texture_Lightmap;
3698         CGparameter fp_Texture_Deluxemap;
3699         CGparameter fp_Texture_Attenuation;
3700         CGparameter fp_Texture_Cube;
3701         CGparameter fp_Texture_Refraction;
3702         CGparameter fp_Texture_Reflection;
3703         CGparameter fp_Texture_ShadowMapRect;
3704         CGparameter fp_Texture_ShadowMapCube;
3705         CGparameter fp_Texture_ShadowMap2D;
3706         CGparameter fp_Texture_CubeProjection;
3707         CGparameter fp_Texture_ScreenDepth;
3708         CGparameter fp_Texture_ScreenNormalMap;
3709         CGparameter fp_Texture_ScreenDiffuse;
3710         CGparameter fp_Texture_ScreenSpecular;
3711         CGparameter fp_Alpha;
3712         CGparameter fp_BloomBlur_Parameters;
3713         CGparameter fp_ClientTime;
3714         CGparameter fp_Color_Ambient;
3715         CGparameter fp_Color_Diffuse;
3716         CGparameter fp_Color_Specular;
3717         CGparameter fp_Color_Glow;
3718         CGparameter fp_Color_Pants;
3719         CGparameter fp_Color_Shirt;
3720         CGparameter fp_DeferredColor_Ambient;
3721         CGparameter fp_DeferredColor_Diffuse;
3722         CGparameter fp_DeferredColor_Specular;
3723         CGparameter fp_DeferredMod_Diffuse;
3724         CGparameter fp_DeferredMod_Specular;
3725         CGparameter fp_DistortScaleRefractReflect;
3726         CGparameter fp_EyePosition;
3727         CGparameter fp_FogColor;
3728         CGparameter fp_FogHeightFade;
3729         CGparameter fp_FogPlane;
3730         CGparameter fp_FogPlaneViewDist;
3731         CGparameter fp_FogRangeRecip;
3732         CGparameter fp_LightColor;
3733         CGparameter fp_LightDir;
3734         CGparameter fp_LightPosition;
3735         CGparameter fp_OffsetMapping_Scale;
3736         CGparameter fp_PixelSize;
3737         CGparameter fp_ReflectColor;
3738         CGparameter fp_ReflectFactor;
3739         CGparameter fp_ReflectOffset;
3740         CGparameter fp_RefractColor;
3741         CGparameter fp_Saturation;
3742         CGparameter fp_ScreenCenterRefractReflect;
3743         CGparameter fp_ScreenScaleRefractReflect;
3744         CGparameter fp_ScreenToDepth;
3745         CGparameter fp_ShadowMap_Parameters;
3746         CGparameter fp_ShadowMap_TextureScale;
3747         CGparameter fp_SpecularPower;
3748         CGparameter fp_UserVec1;
3749         CGparameter fp_UserVec2;
3750         CGparameter fp_UserVec3;
3751         CGparameter fp_UserVec4;
3752         CGparameter fp_ViewTintColor;
3753         CGparameter fp_ViewToLight;
3754         CGparameter fp_PixelToScreenTexCoord;
3755 }
3756 r_cg_permutation_t;
3757
3758 /// information about each possible shader permutation
3759 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3760 /// currently selected permutation
3761 r_cg_permutation_t *r_cg_permutation;
3762 /// storage for permutations linked in the hash table
3763 memexpandablearray_t r_cg_permutationarray;
3764
3765 #define CHECKCGERROR {CGerror err = cgGetError(), err2 = err;if (err){Con_Printf("%s:%i CG error %i: %s : %s\n", __FILE__, __LINE__, err, cgGetErrorString(err), cgGetLastErrorString(&err2));if (err == 1) Con_Printf("last listing:\n%s\n", cgGetLastListing(vid.cgcontext));}}
3766
3767 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3768 {
3769         //unsigned int hashdepth = 0;
3770         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3771         r_cg_permutation_t *p;
3772         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3773         {
3774                 if (p->mode == mode && p->permutation == permutation)
3775                 {
3776                         //if (hashdepth > 10)
3777                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3778                         return p;
3779                 }
3780                 //hashdepth++;
3781         }
3782         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3783         p->mode = mode;
3784         p->permutation = permutation;
3785         p->hashnext = r_cg_permutationhash[mode][hashindex];
3786         r_cg_permutationhash[mode][hashindex] = p;
3787         //if (hashdepth > 10)
3788         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3789         return p;
3790 }
3791
3792 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3793 {
3794         char *shaderstring;
3795         if (!filename || !filename[0])
3796                 return NULL;
3797         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3798         if (shaderstring)
3799         {
3800                 if (printfromdisknotice)
3801                         Con_DPrintf("from disk %s... ", filename);
3802                 return shaderstring;
3803         }
3804         else if (!strcmp(filename, "cg/default.cg"))
3805         {
3806                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(builtincgshaderstring) + 1);
3807                 memcpy(shaderstring, builtincgshaderstring, strlen(builtincgshaderstring) + 1);
3808         }
3809         return shaderstring;
3810 }
3811
3812 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3813 {
3814         int i;
3815         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3816         int vertstrings_count = 0, vertstring_length = 0;
3817         int geomstrings_count = 0, geomstring_length = 0;
3818         int fragstrings_count = 0, fragstring_length = 0;
3819         char *t;
3820         char *vertexstring, *geometrystring, *fragmentstring;
3821         char *vertstring, *geomstring, *fragstring;
3822         const char *vertstrings_list[32+3];
3823         const char *geomstrings_list[32+3];
3824         const char *fragstrings_list[32+3];
3825         char permutationname[256];
3826         CGprofile vertexProfile;
3827         CGprofile fragmentProfile;
3828
3829         if (p->compiled)
3830                 return;
3831         p->compiled = true;
3832         p->vprogram = NULL;
3833         p->fprogram = NULL;
3834
3835         permutationname[0] = 0;
3836         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3837         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3838         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3839
3840         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3841
3842         // the first pretext is which type of shader to compile as
3843         // (later these will all be bound together as a program object)
3844         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3845         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3846         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3847
3848         // the second pretext is the mode (for example a light source)
3849         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3850         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3851         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3852         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3853
3854         // now add all the permutation pretexts
3855         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3856         {
3857                 if (permutation & (1<<i))
3858                 {
3859                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3860                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3861                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3862                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3863                 }
3864                 else
3865                 {
3866                         // keep line numbers correct
3867                         vertstrings_list[vertstrings_count++] = "\n";
3868                         geomstrings_list[geomstrings_count++] = "\n";
3869                         fragstrings_list[fragstrings_count++] = "\n";
3870                 }
3871         }
3872
3873         // now append the shader text itself
3874         vertstrings_list[vertstrings_count++] = vertexstring;
3875         geomstrings_list[geomstrings_count++] = geometrystring;
3876         fragstrings_list[fragstrings_count++] = fragmentstring;
3877
3878         // if any sources were NULL, clear the respective list
3879         if (!vertexstring)
3880                 vertstrings_count = 0;
3881         if (!geometrystring)
3882                 geomstrings_count = 0;
3883         if (!fragmentstring)
3884                 fragstrings_count = 0;
3885
3886         vertstring_length = 0;
3887         for (i = 0;i < vertstrings_count;i++)
3888                 vertstring_length += strlen(vertstrings_list[i]);
3889         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3890         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3891                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3892
3893         geomstring_length = 0;
3894         for (i = 0;i < geomstrings_count;i++)
3895                 geomstring_length += strlen(geomstrings_list[i]);
3896         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3897         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3898                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
3899
3900         fragstring_length = 0;
3901         for (i = 0;i < fragstrings_count;i++)
3902                 fragstring_length += strlen(fragstrings_list[i]);
3903         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
3904         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
3905                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
3906
3907         CHECKGLERROR
3908         CHECKCGERROR
3909         //vertexProfile = CG_PROFILE_ARBVP1;
3910         //fragmentProfile = CG_PROFILE_ARBFP1;
3911         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
3912         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
3913         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
3914         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
3915         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
3916         CHECKGLERROR
3917
3918         // compile the vertex program
3919         if (vertstring[0] && (p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL)))
3920         {
3921                 CHECKCGERROR
3922 #if 0
3923                 cgCompileProgram(p->vprogram);CHECKCGERROR
3924                 if (!cgIsProgramCompiled(p->vprogram))
3925                 {
3926                         CHECKCGERROR
3927                         cgDestroyProgram(p->vprogram);CHECKCGERROR
3928                         p->vprogram = 0;
3929                 }
3930                 else
3931 #endif
3932                 {
3933                         cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
3934                         cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
3935                         // look up all the uniform variable names we care about, so we don't
3936                         // have to look them up every time we set them
3937                         CHECKCGERROR
3938                         p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
3939                         p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
3940                         p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
3941                         p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
3942                         p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
3943                         p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
3944                         p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
3945                         p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
3946                         p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
3947                         CHECKCGERROR
3948                 }
3949         }
3950
3951         // compile the fragment program
3952         if (fragstring[0] && (p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL)))
3953         {
3954 #if 0
3955                 cgCompileProgram(p->fprogram);CHECKCGERROR
3956                 if (!cgIsProgramCompiled(p->fprogram))
3957                 {
3958                         CHECKCGERROR
3959                         cgDestroyProgram(p->fprogram);CHECKCGERROR
3960                         p->fprogram = 0;
3961                 }
3962                 else
3963 #endif
3964                 {
3965                         cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
3966                         cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
3967                         CHECKCGERROR
3968                         p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
3969                         p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
3970                         p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
3971                         p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
3972                         p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
3973                         p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
3974                         p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
3975                         p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
3976                         p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
3977                         p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
3978                         p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
3979                         p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
3980                         p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
3981                         p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
3982                         p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
3983                         p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
3984                         p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
3985                         p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
3986                         p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
3987                         p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
3988                         p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
3989                         p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
3990                         p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
3991                         p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
3992                         p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
3993                         p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
3994                         p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
3995                         p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
3996                         p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
3997                         p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
3998                         p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
3999                         p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4000                         p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4001                         p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4002                         p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4003                         p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4004                         p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4005                         p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4006                         p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4007                         p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4008                         p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4009                         p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4010                         p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4011                         p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4012                         p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4013                         p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4014                         p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4015                         p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4016                         p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4017                         p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4018                         p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4019                         p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4020                         p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4021                         p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4022                         p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4023                         p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4024                         p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4025                         p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4026                         p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4027                         p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4028                         p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4029                         p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4030                         p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4031                         p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4032                         p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4033                         p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4034                         p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4035                         p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4036                         p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4037                         p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4038                         p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4039                         p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4040                         CHECKCGERROR
4041                 }
4042         }
4043
4044         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4045                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4046         else
4047                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4048
4049         // free the strings
4050         if (vertstring)
4051                 Mem_Free(vertstring);
4052         if (geomstring)
4053                 Mem_Free(geomstring);
4054         if (fragstring)
4055                 Mem_Free(fragstring);
4056         if (vertexstring)
4057                 Mem_Free(vertexstring);
4058         if (geometrystring)
4059                 Mem_Free(geometrystring);
4060         if (fragmentstring)
4061                 Mem_Free(fragmentstring);
4062 }
4063
4064 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4065 {
4066         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4067         CHECKGLERROR
4068         CHECKCGERROR
4069         if (r_cg_permutation != perm)
4070         {
4071                 r_cg_permutation = perm;
4072                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4073                 {
4074                         if (!r_cg_permutation->compiled)
4075                                 R_CG_CompilePermutation(perm, mode, permutation);
4076                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4077                         {
4078                                 // remove features until we find a valid permutation
4079                                 int i;
4080                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4081                                 {
4082                                         // reduce i more quickly whenever it would not remove any bits
4083                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4084                                         if (!(permutation & j))
4085                                                 continue;
4086                                         permutation -= j;
4087                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4088                                         if (!r_cg_permutation->compiled)
4089                                                 R_CG_CompilePermutation(perm, mode, permutation);
4090                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4091                                                 break;
4092                                 }
4093                                 if (i >= SHADERPERMUTATION_COUNT)
4094                                 {
4095                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4096                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4097                                         return; // no bit left to clear, entire mode is broken
4098                                 }
4099                         }
4100                 }
4101                 CHECKGLERROR
4102                 CHECKCGERROR
4103                 if (r_cg_permutation->vprogram)
4104                 {
4105                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4106                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4107                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4108                 }
4109                 else
4110                 {
4111                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4112                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4113                 }
4114                 if (r_cg_permutation->fprogram)
4115                 {
4116                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4117                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4118                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4119                 }
4120                 else
4121                 {
4122                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4123                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4124                 }
4125         }
4126         CHECKCGERROR
4127         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4128         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4129 }
4130
4131 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4132 {
4133         cgGLSetTextureParameter(param, R_GetTexture(tex));
4134         cgGLEnableTextureParameter(param);
4135 }
4136 #endif
4137
4138 void R_GLSL_Restart_f(void)
4139 {
4140         unsigned int i, limit;
4141         switch(vid.renderpath)
4142         {
4143         case RENDERPATH_GL20:
4144                 {
4145                         r_glsl_permutation_t *p;
4146                         r_glsl_permutation = NULL;
4147                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4148                         for (i = 0;i < limit;i++)
4149                         {
4150                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4151                                 {
4152                                         GL_Backend_FreeProgram(p->program);
4153                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4154                                 }
4155                         }
4156                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4157                 }
4158                 break;
4159         case RENDERPATH_CGGL:
4160 #ifdef SUPPORTCG
4161                 {
4162                         r_cg_permutation_t *p;
4163                         r_cg_permutation = NULL;
4164                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4165                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4166                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4167                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4168                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4169                         for (i = 0;i < limit;i++)
4170                         {
4171                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4172                                 {
4173                                         if (p->vprogram)
4174                                                 cgDestroyProgram(p->vprogram);
4175                                         if (p->fprogram)
4176                                                 cgDestroyProgram(p->fprogram);
4177                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4178                                 }
4179                         }
4180                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4181                 }
4182                 break;
4183 #endif
4184         case RENDERPATH_GL13:
4185         case RENDERPATH_GL11:
4186                 break;
4187         }
4188 }
4189
4190 void R_GLSL_DumpShader_f(void)
4191 {
4192         int i;
4193         qfile_t *file;
4194
4195         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4196         if (file)
4197         {
4198                 FS_Print(file, "/* The engine may define the following macros:\n");
4199                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4200                 for (i = 0;i < SHADERMODE_COUNT;i++)
4201                         FS_Print(file, glslshadermodeinfo[i].pretext);
4202                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4203                         FS_Print(file, shaderpermutationinfo[i].pretext);
4204                 FS_Print(file, "*/\n");
4205                 FS_Print(file, builtinshaderstring);
4206                 FS_Close(file);
4207                 Con_Printf("glsl/default.glsl written\n");
4208         }
4209         else
4210                 Con_Printf("failed to write to glsl/default.glsl\n");
4211
4212 #ifdef SUPPORTCG
4213         file = FS_OpenRealFile("cg/default.cg", "w", false);
4214         if (file)
4215         {
4216                 FS_Print(file, "/* The engine may define the following macros:\n");
4217                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4218                 for (i = 0;i < SHADERMODE_COUNT;i++)
4219                         FS_Print(file, cgshadermodeinfo[i].pretext);
4220                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4221                         FS_Print(file, shaderpermutationinfo[i].pretext);
4222                 FS_Print(file, "*/\n");
4223                 FS_Print(file, builtincgshaderstring);
4224                 FS_Close(file);
4225                 Con_Printf("cg/default.cg written\n");
4226         }
4227         else
4228                 Con_Printf("failed to write to cg/default.cg\n");
4229 #endif
4230 }
4231
4232 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4233 {
4234         if (!second)
4235                 texturemode = GL_MODULATE;
4236         switch (vid.renderpath)
4237         {
4238         case RENDERPATH_GL20:
4239                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4240                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4241                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4242                 break;
4243         case RENDERPATH_CGGL:
4244 #ifdef SUPPORTCG
4245                 CHECKCGERROR
4246                 R_SetupShader_SetPermutationCG(SHADERMODE_GENERIC, (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (r_shadow_glossexact.integer ? SHADERPERMUTATION_EXACTSPECULARMATH : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4247                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4248                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4249 #endif
4250                 break;
4251         case RENDERPATH_GL13:
4252                 R_Mesh_TexBind(0, first );
4253                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4254                 R_Mesh_TexBind(1, second);
4255                 if (second)
4256                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4257                 break;
4258         case RENDERPATH_GL11:
4259                 R_Mesh_TexBind(0, first );
4260                 break;
4261         }
4262 }
4263
4264 void R_SetupShader_DepthOrShadow(void)
4265 {
4266         switch (vid.renderpath)
4267         {
4268         case RENDERPATH_GL20:
4269                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4270                 break;
4271         case RENDERPATH_CGGL:
4272 #ifdef SUPPORTCG
4273                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4274 #endif
4275                 break;
4276         case RENDERPATH_GL13:
4277                 R_Mesh_TexBind(0, 0);
4278                 R_Mesh_TexBind(1, 0);
4279                 break;
4280         case RENDERPATH_GL11:
4281                 R_Mesh_TexBind(0, 0);
4282                 break;
4283         }
4284 }
4285
4286 void R_SetupShader_ShowDepth(void)
4287 {
4288         switch (vid.renderpath)
4289         {
4290         case RENDERPATH_GL20:
4291                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4292                 break;
4293         case RENDERPATH_CGGL:
4294 #ifdef SUPPORTCG
4295                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4296 #endif
4297                 break;
4298         case RENDERPATH_GL13:
4299                 break;
4300         case RENDERPATH_GL11:
4301                 break;
4302         }
4303 }
4304
4305 extern qboolean r_shadow_usingdeferredprepass;
4306 extern cvar_t r_shadow_deferred_8bitrange;
4307 extern rtexture_t *r_shadow_attenuationgradienttexture;
4308 extern rtexture_t *r_shadow_attenuation2dtexture;
4309 extern rtexture_t *r_shadow_attenuation3dtexture;
4310 extern qboolean r_shadow_usingshadowmaprect;
4311 extern qboolean r_shadow_usingshadowmapcube;
4312 extern qboolean r_shadow_usingshadowmap2d;
4313 extern float r_shadow_shadowmap_texturescale[2];
4314 extern float r_shadow_shadowmap_parameters[4];
4315 extern qboolean r_shadow_shadowmapvsdct;
4316 extern qboolean r_shadow_shadowmapsampler;
4317 extern int r_shadow_shadowmappcf;
4318 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4319 extern rtexture_t *r_shadow_shadowmap2dtexture;
4320 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4321 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4322 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4323 extern int r_shadow_prepass_width;
4324 extern int r_shadow_prepass_height;
4325 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4326 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4327 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4328 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4329 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4330 {
4331         // select a permutation of the lighting shader appropriate to this
4332         // combination of texture, entity, light source, and fogging, only use the
4333         // minimum features necessary to avoid wasting rendering time in the
4334         // fragment shader on features that are not being used
4335         unsigned int permutation = 0;
4336         unsigned int mode = 0;
4337         float m16f[16];
4338         // TODO: implement geometry-shader based shadow volumes someday
4339         if (r_glsl_offsetmapping.integer)
4340         {
4341                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4342                 if (r_glsl_offsetmapping_reliefmapping.integer)
4343                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4344         }
4345         if (rsurfacepass == RSURFPASS_BACKGROUND)
4346         {
4347                 // distorted background
4348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4349                         mode = SHADERMODE_WATER;
4350                 else
4351                         mode = SHADERMODE_REFRACTION;
4352         }
4353         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4354         {
4355                 // normalmap (deferred prepass), may use alpha test on diffuse
4356                 mode = SHADERMODE_DEFERREDGEOMETRY;
4357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4358                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4359                 if (r_glsl_offsetmapping.integer)
4360                 {
4361                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4362                         if (r_glsl_offsetmapping_reliefmapping.integer)
4363                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4364                 }
4365         }
4366         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4367         {
4368                 // light source
4369                 mode = SHADERMODE_LIGHTSOURCE;
4370                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4371                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4372                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4373                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4374                 if (diffusescale > 0)
4375                         permutation |= SHADERPERMUTATION_DIFFUSE;
4376                 if (specularscale > 0)
4377                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4378                 if (r_refdef.fogenabled)
4379                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4380                 if (rsurface.texture->colormapping)
4381                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4382                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4383                 {
4384                         if (r_shadow_usingshadowmaprect)
4385                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4386                         if (r_shadow_usingshadowmap2d)
4387                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4388                         if (r_shadow_usingshadowmapcube)
4389                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4390                         else if(r_shadow_shadowmapvsdct)
4391                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4392
4393                         if (r_shadow_shadowmapsampler)
4394                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4395                         if (r_shadow_shadowmappcf > 1)
4396                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4397                         else if (r_shadow_shadowmappcf)
4398                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4399                 }
4400         }
4401         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4402         {
4403                 // unshaded geometry (fullbright or ambient model lighting)
4404                 mode = SHADERMODE_FLATCOLOR;
4405                 ambientscale = diffusescale = specularscale = 0;
4406                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4407                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4408                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4409                         permutation |= SHADERPERMUTATION_GLOW;
4410                 if (r_refdef.fogenabled)
4411                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4412                 if (rsurface.texture->colormapping)
4413                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4414                 if (r_glsl_offsetmapping.integer)
4415                 {
4416                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4417                         if (r_glsl_offsetmapping_reliefmapping.integer)
4418                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4419                 }
4420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4421                         permutation |= SHADERPERMUTATION_REFLECTION;
4422         }
4423         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4424         {
4425                 // directional model lighting
4426                 mode = SHADERMODE_LIGHTDIRECTION;
4427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4429                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4430                         permutation |= SHADERPERMUTATION_GLOW;
4431                 permutation |= SHADERPERMUTATION_DIFFUSE;
4432                 if (specularscale > 0)
4433                         permutation |= SHADERPERMUTATION_SPECULAR;
4434                 if (r_refdef.fogenabled)
4435                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4436                 if (rsurface.texture->colormapping)
4437                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4439                         permutation |= SHADERPERMUTATION_REFLECTION;
4440                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4441                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4442         }
4443         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4444         {
4445                 // ambient model lighting
4446                 mode = SHADERMODE_LIGHTDIRECTION;
4447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4448                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4449                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4450                         permutation |= SHADERPERMUTATION_GLOW;
4451                 if (r_refdef.fogenabled)
4452                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4453                 if (rsurface.texture->colormapping)
4454                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4456                         permutation |= SHADERPERMUTATION_REFLECTION;
4457                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4458                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4459         }
4460         else
4461         {
4462                 // lightmapped wall
4463                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4464                 {
4465                         // deluxemapping (light direction texture)
4466                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4468                         else
4469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4470                         permutation |= SHADERPERMUTATION_DIFFUSE;
4471                         if (specularscale > 0)
4472                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4473                 }
4474                 else if (r_glsl_deluxemapping.integer >= 2)
4475                 {
4476                         // fake deluxemapping (uniform light direction in tangentspace)
4477                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4478                         permutation |= SHADERPERMUTATION_DIFFUSE;
4479                         if (specularscale > 0)
4480                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4481                 }
4482                 else if (rsurface.uselightmaptexture)
4483                 {
4484                         // ordinary lightmapping (q1bsp, q3bsp)
4485                         mode = SHADERMODE_LIGHTMAP;
4486                 }
4487                 else
4488                 {
4489                         // ordinary vertex coloring (q3bsp)
4490                         mode = SHADERMODE_VERTEXCOLOR;
4491                 }
4492                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4493                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4494                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4495                         permutation |= SHADERPERMUTATION_GLOW;
4496                 if (r_refdef.fogenabled)
4497                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4498                 if (rsurface.texture->colormapping)
4499                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4500                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4501                         permutation |= SHADERPERMUTATION_REFLECTION;
4502                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4503                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4504         }
4505         if(permutation & SHADERPERMUTATION_SPECULAR)
4506                 if(r_shadow_glossexact.integer)
4507                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4508         if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) && r_shadow_usingdeferredprepass)
4509                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4510         switch(vid.renderpath)
4511         {
4512         case RENDERPATH_GL20:
4513                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4514                 if (mode == SHADERMODE_LIGHTSOURCE)
4515                 {
4516                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4517                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4518                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4519                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);
4520                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);
4521                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
4522         
4523                         // additive passes are only darkened by fog, not tinted
4524                         if (r_glsl_permutation->loc_FogColor >= 0)
4525                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4526                         if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
4527                         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]);
4528                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4529                 }
4530                 else
4531                 {
4532                         if (mode == SHADERMODE_FLATCOLOR)
4533                         {
4534                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4535                         }
4536                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4537                         {
4538                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);
4539                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);
4540                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4541                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);
4542                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4543                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
4544                                 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]);
4545                         }
4546                         else
4547                         {
4548                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);
4549                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
4550                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
4551                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
4552                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
4553                         }
4554                         // additive passes are only darkened by fog, not tinted
4555                         if (r_glsl_permutation->loc_FogColor >= 0)
4556                         {
4557                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4558                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4559                                 else
4560                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4561                         }
4562                         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);
4563                         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]);
4564                         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]);
4565                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4566                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4567                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4568                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4569                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4570                 }
4571                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4572                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4573                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4574                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4575                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4576                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4577                 {
4578                         if (rsurface.texture->pantstexture)
4579                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4580                         else
4581                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4582                 }
4583                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4584                 {
4585                         if (rsurface.texture->shirttexture)
4586                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4587                         else
4588                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4589                 }
4590                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
4591                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4592                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4593                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4594                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4595                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
4596                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4597
4598         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4599         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4600         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4601                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4602                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4603                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4604                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4605                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4606                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4607                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4608                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4609                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4610                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4611                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4612                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4613                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4614                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4615                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4616                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4617                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4618                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4619                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4620                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4621                 if (rsurface.rtlight)
4622                 {
4623                         if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4624                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4625                         if (r_shadow_usingshadowmapcube)
4626                                 if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4627                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4628                         if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4629                 }
4630                 CHECKGLERROR
4631                 break;
4632         case RENDERPATH_CGGL:
4633 #ifdef SUPPORTCG
4634                 R_SetupShader_SetPermutationCG(mode, permutation);
4635                 if (mode == SHADERMODE_LIGHTSOURCE)
4636                 {
4637                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4638                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4639                 }
4640                 else
4641                 {
4642                         if (mode == SHADERMODE_LIGHTDIRECTION)
4643                         {
4644                                 if (r_cg_permutation->vp_LightDir) cgGLSetParameter3f(r_cg_permutation->vp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4645                         }
4646                 }
4647                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4648                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4649                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4650                 if (r_cg_permutation->vp_FogPlane) cgGLSetParameter4f(r_cg_permutation->vp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4651                 CHECKGLERROR
4652
4653                 if (mode == SHADERMODE_LIGHTSOURCE)
4654                 {
4655                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4656                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4657                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0] * ambientscale, rsurface.colormod[1] * ambientscale, rsurface.colormod[2] * ambientscale);CHECKCGERROR
4658                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.colormod[0] * diffusescale, rsurface.colormod[1] * diffusescale, rsurface.colormod[2] * diffusescale);CHECKCGERROR
4659                         if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);CHECKCGERROR
4660
4661                         // additive passes are only darkened by fog, not tinted
4662                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
4663                         if (r_cg_permutation->fp_ShadowMap_TextureScale) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4664                         if (r_cg_permutation->fp_ShadowMap_Parameters) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4665                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4666                 }
4667                 else
4668                 {
4669                         if (mode == SHADERMODE_FLATCOLOR)
4670                         {
4671                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
4672                         }
4673                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4674                         {
4675                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * rsurface.colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * rsurface.colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * rsurface.colormod[2]);CHECKCGERROR
4676                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * rsurface.colormod[0], r_refdef.lightmapintensity * rsurface.colormod[1], r_refdef.lightmapintensity * rsurface.colormod[2]);CHECKCGERROR
4677                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4678                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4679                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4680                                 if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);CHECKCGERROR
4681                                 if (r_cg_permutation->fp_LightDir) cgGLSetParameter3f(r_cg_permutation->fp_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);CHECKCGERROR
4682                         }
4683                         else
4684                         {
4685                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * rsurface.colormod[0], r_refdef.scene.ambient * rsurface.colormod[1], r_refdef.scene.ambient * rsurface.colormod[2]);CHECKCGERROR
4686                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);CHECKCGERROR
4687                                 if (r_cg_permutation->fp_Color_Specular) cgGLSetParameter3f(r_cg_permutation->fp_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);CHECKCGERROR
4688                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, rsurface.colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, rsurface.colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4689                                 if (r_cg_permutation->fp_DeferredMod_Specular) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
4690                         }
4691                         // additive passes are only darkened by fog, not tinted
4692                         if (r_cg_permutation->fp_FogColor)
4693                         {
4694                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4695                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
4696                                 else
4697                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4698                                 CHECKCGERROR
4699                         }
4700                         if (r_cg_permutation->fp_DistortScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_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);CHECKCGERROR
4701                         if (r_cg_permutation->fp_ScreenScaleRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);CHECKCGERROR
4702                         if (r_cg_permutation->fp_ScreenCenterRefractReflect) cgGLSetParameter4f(r_cg_permutation->fp_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);CHECKCGERROR
4703                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
4704                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
4705                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
4706                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
4707                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4708                 }
4709                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
4710                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
4711                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4712                 if (r_cg_permutation->fp_Color_Pants)
4713                 {
4714                         if (rsurface.texture->pantstexture)
4715                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4716                         else
4717                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
4718                         CHECKCGERROR
4719                 }
4720                 if (r_cg_permutation->fp_Color_Shirt)
4721                 {
4722                         if (rsurface.texture->shirttexture)
4723                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4724                         else
4725                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
4726                         CHECKCGERROR
4727                 }
4728                 if (r_cg_permutation->fp_FogPlane) cgGLSetParameter4f(r_cg_permutation->fp_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);CHECKCGERROR
4729                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
4730                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
4731                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
4732                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
4733                 if (r_cg_permutation->fp_ScreenToDepth) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4734                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4735
4736         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
4737         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
4738         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
4739                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
4740                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
4741                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
4742                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
4743                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
4744                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
4745                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
4746                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
4747                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
4748                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
4749                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
4750                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
4751                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
4752                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4753                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
4754                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
4755                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4756                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4757                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
4758                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
4759                 if (rsurface.rtlight)
4760                 {
4761                         if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4762                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4763                         if (r_shadow_usingshadowmapcube)
4764                                 if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4765                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4766                         if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4767                 }
4768
4769                 CHECKGLERROR
4770 #endif
4771                 break;
4772         case RENDERPATH_GL13:
4773         case RENDERPATH_GL11:
4774                 break;
4775         }
4776 }
4777
4778 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
4779 {
4780         // select a permutation of the lighting shader appropriate to this
4781         // combination of texture, entity, light source, and fogging, only use the
4782         // minimum features necessary to avoid wasting rendering time in the
4783         // fragment shader on features that are not being used
4784         unsigned int permutation = 0;
4785         unsigned int mode = 0;
4786         const float *lightcolorbase = rtlight->currentcolor;
4787         float ambientscale = rtlight->ambientscale;
4788         float diffusescale = rtlight->diffusescale;
4789         float specularscale = rtlight->specularscale;
4790         // this is the location of the light in view space
4791         vec3_t viewlightorigin;
4792         // this transforms from view space (camera) to light space (cubemap)
4793         matrix4x4_t viewtolight;
4794         matrix4x4_t lighttoview;
4795         float viewtolight16f[16];
4796         float range = 1.0f / r_shadow_deferred_8bitrange.value;
4797         // light source
4798         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
4799         if (rtlight->currentcubemap != r_texture_whitecube)
4800                 permutation |= SHADERPERMUTATION_CUBEFILTER;
4801         if (diffusescale > 0)
4802                 permutation |= SHADERPERMUTATION_DIFFUSE;
4803         if (specularscale > 0)
4804         {
4805                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4806                 if (r_shadow_glossexact.integer)
4807                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4808         }
4809         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4810         {
4811                 if (r_shadow_usingshadowmaprect)
4812                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4813                 if (r_shadow_usingshadowmap2d)
4814                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4815                 if (r_shadow_usingshadowmapcube)
4816                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4817                 else if(r_shadow_shadowmapvsdct)
4818                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4819
4820                 if (r_shadow_shadowmapsampler)
4821                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4822                 if (r_shadow_shadowmappcf > 1)
4823                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4824                 else if (r_shadow_shadowmappcf)
4825                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4826         }
4827         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
4828         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
4829         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
4830         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
4831         switch(vid.renderpath)
4832         {
4833         case RENDERPATH_GL20:
4834                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4835                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
4836                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
4837                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
4838                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
4839                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
4840                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
4841                 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]);
4842                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4843                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
4844                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4845
4846                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
4847                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
4848                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
4849                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
4850                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
4851                 if (r_shadow_usingshadowmapcube)
4852                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4853                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
4854                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
4855                 break;
4856         case RENDERPATH_CGGL:
4857 #ifdef SUPPORTCG
4858                 R_SetupShader_SetPermutationCG(mode, permutation);
4859                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
4860                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
4861                 if (r_cg_permutation->fp_DeferredColor_Ambient    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);CHECKCGERROR
4862                 if (r_cg_permutation->fp_DeferredColor_Diffuse    ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);CHECKCGERROR
4863                 if (r_cg_permutation->fp_DeferredColor_Specular   ) cgGLSetParameter3f(r_cg_permutation->fp_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);CHECKCGERROR
4864                 if (r_cg_permutation->fp_ShadowMap_TextureScale   ) cgGLSetParameter2f(r_cg_permutation->fp_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);CHECKCGERROR
4865                 if (r_cg_permutation->fp_ShadowMap_Parameters     ) cgGLSetParameter4f(r_cg_permutation->fp_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);CHECKCGERROR
4866                 if (r_cg_permutation->fp_SpecularPower            ) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
4867                 if (r_cg_permutation->fp_ScreenToDepth            ) cgGLSetParameter2f(r_cg_permutation->fp_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);CHECKCGERROR
4868                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
4869
4870                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
4871                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
4872                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
4873                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
4874                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
4875                 if (r_shadow_usingshadowmapcube)
4876                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
4877                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
4878                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
4879 #endif
4880                 break;
4881         case RENDERPATH_GL13:
4882         case RENDERPATH_GL11:
4883                 break;
4884         }
4885 }
4886
4887 #define SKINFRAME_HASH 1024
4888
4889 typedef struct
4890 {
4891         int loadsequence; // incremented each level change
4892         memexpandablearray_t array;
4893         skinframe_t *hash[SKINFRAME_HASH];
4894 }
4895 r_skinframe_t;
4896 r_skinframe_t r_skinframe;
4897
4898 void R_SkinFrame_PrepareForPurge(void)
4899 {
4900         r_skinframe.loadsequence++;
4901         // wrap it without hitting zero
4902         if (r_skinframe.loadsequence >= 200)
4903                 r_skinframe.loadsequence = 1;
4904 }
4905
4906 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
4907 {
4908         if (!skinframe)
4909                 return;
4910         // mark the skinframe as used for the purging code
4911         skinframe->loadsequence = r_skinframe.loadsequence;
4912 }
4913
4914 void R_SkinFrame_Purge(void)
4915 {
4916         int i;
4917         skinframe_t *s;
4918         for (i = 0;i < SKINFRAME_HASH;i++)
4919         {
4920                 for (s = r_skinframe.hash[i];s;s = s->next)
4921                 {
4922                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
4923                         {
4924                                 if (s->merged == s->base)
4925                                         s->merged = NULL;
4926                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
4927                                 R_PurgeTexture(s->stain );s->stain  = NULL;
4928                                 R_PurgeTexture(s->merged);s->merged = NULL;
4929                                 R_PurgeTexture(s->base  );s->base   = NULL;
4930                                 R_PurgeTexture(s->pants );s->pants  = NULL;
4931                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
4932                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
4933                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
4934                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
4935                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
4936                                 s->loadsequence = 0;
4937                         }
4938                 }
4939         }
4940 }
4941
4942 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
4943         skinframe_t *item;
4944         char basename[MAX_QPATH];
4945
4946         Image_StripImageExtension(name, basename, sizeof(basename));
4947
4948         if( last == NULL ) {
4949                 int hashindex;
4950                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4951                 item = r_skinframe.hash[hashindex];
4952         } else {
4953                 item = last->next;
4954         }
4955
4956         // linearly search through the hash bucket
4957         for( ; item ; item = item->next ) {
4958                 if( !strcmp( item->basename, basename ) ) {
4959                         return item;
4960                 }
4961         }
4962         return NULL;
4963 }
4964
4965 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
4966 {
4967         skinframe_t *item;
4968         int hashindex;
4969         char basename[MAX_QPATH];
4970
4971         Image_StripImageExtension(name, basename, sizeof(basename));
4972
4973         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
4974         for (item = r_skinframe.hash[hashindex];item;item = item->next)
4975                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
4976                         break;
4977
4978         if (!item) {
4979                 rtexture_t *dyntexture;
4980                 // check whether its a dynamic texture
4981                 dyntexture = CL_GetDynTexture( basename );
4982                 if (!add && !dyntexture)
4983                         return NULL;
4984                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
4985                 memset(item, 0, sizeof(*item));
4986                 strlcpy(item->basename, basename, sizeof(item->basename));
4987                 item->base = dyntexture; // either NULL or dyntexture handle
4988                 item->textureflags = textureflags;
4989                 item->comparewidth = comparewidth;
4990                 item->compareheight = compareheight;
4991                 item->comparecrc = comparecrc;
4992                 item->next = r_skinframe.hash[hashindex];
4993                 r_skinframe.hash[hashindex] = item;
4994         }
4995         else if( item->base == NULL )
4996         {
4997                 rtexture_t *dyntexture;
4998                 // check whether its a dynamic texture
4999                 // 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]
5000                 dyntexture = CL_GetDynTexture( basename );
5001                 item->base = dyntexture; // either NULL or dyntexture handle
5002         }
5003
5004         R_SkinFrame_MarkUsed(item);
5005         return item;
5006 }
5007
5008 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5009         { \
5010                 unsigned long long avgcolor[5], wsum; \
5011                 int pix, comp, w; \
5012                 avgcolor[0] = 0; \
5013                 avgcolor[1] = 0; \
5014                 avgcolor[2] = 0; \
5015                 avgcolor[3] = 0; \
5016                 avgcolor[4] = 0; \
5017                 wsum = 0; \
5018                 for(pix = 0; pix < cnt; ++pix) \
5019                 { \
5020                         w = 0; \
5021                         for(comp = 0; comp < 3; ++comp) \
5022                                 w += getpixel; \
5023                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5024                         { \
5025                                 ++wsum; \
5026                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5027                                 w = getpixel; \
5028                                 for(comp = 0; comp < 3; ++comp) \
5029                                         avgcolor[comp] += getpixel * w; \
5030                                 avgcolor[3] += w; \
5031                         } \
5032                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5033                         avgcolor[4] += getpixel; \
5034                 } \
5035                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5036                         avgcolor[3] = 1; \
5037                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5038                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5039                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5040                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5041         }
5042
5043 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5044 {
5045         int j;
5046         unsigned char *pixels;
5047         unsigned char *bumppixels;
5048         unsigned char *basepixels = NULL;
5049         int basepixels_width = 0;
5050         int basepixels_height = 0;
5051         skinframe_t *skinframe;
5052         rtexture_t *ddsbase = NULL;
5053         qboolean ddshasalpha = false;
5054         float ddsavgcolor[4];
5055         char basename[MAX_QPATH];
5056
5057         if (cls.state == ca_dedicated)
5058                 return NULL;
5059
5060         // return an existing skinframe if already loaded
5061         // if loading of the first image fails, don't make a new skinframe as it
5062         // would cause all future lookups of this to be missing
5063         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5064         if (skinframe && skinframe->base)
5065                 return skinframe;
5066
5067         Image_StripImageExtension(name, basename, sizeof(basename));
5068
5069         // check for DDS texture file first
5070         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5071         {
5072                 basepixels = loadimagepixelsbgra(name, complain, true);
5073                 if (basepixels == NULL)
5074                         return NULL;
5075         }
5076
5077         if (developer_loading.integer)
5078                 Con_Printf("loading skin \"%s\"\n", name);
5079
5080         // we've got some pixels to store, so really allocate this new texture now
5081         if (!skinframe)
5082                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5083         skinframe->stain = NULL;
5084         skinframe->merged = NULL;
5085         skinframe->base = NULL;
5086         skinframe->pants = NULL;
5087         skinframe->shirt = NULL;
5088         skinframe->nmap = NULL;
5089         skinframe->gloss = NULL;
5090         skinframe->glow = NULL;
5091         skinframe->fog = NULL;
5092         skinframe->hasalpha = false;
5093
5094         if (ddsbase)
5095         {
5096                 skinframe->base = ddsbase;
5097                 skinframe->hasalpha = ddshasalpha;
5098                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5099                 if (r_loadfog && skinframe->hasalpha)
5100                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5101                 //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]);
5102         }
5103         else
5104         {
5105                 basepixels_width = image_width;
5106                 basepixels_height = image_height;
5107                 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);
5108                 if (textureflags & TEXF_ALPHA)
5109                 {
5110                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5111                         {
5112                                 if (basepixels[j] < 255)
5113                                 {
5114                                         skinframe->hasalpha = true;
5115                                         break;
5116                                 }
5117                         }
5118                         if (r_loadfog && skinframe->hasalpha)
5119                         {
5120                                 // has transparent pixels
5121                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5122                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5123                                 {
5124                                         pixels[j+0] = 255;
5125                                         pixels[j+1] = 255;
5126                                         pixels[j+2] = 255;
5127                                         pixels[j+3] = basepixels[j+3];
5128                                 }
5129                                 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);
5130                                 Mem_Free(pixels);
5131                         }
5132                 }
5133                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5134                 //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]);
5135                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5136                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5137                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5138                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5139         }
5140
5141         if (r_loaddds)
5142         {
5143                 if (r_loadnormalmap)
5144                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5145                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5146                 if (r_loadgloss)
5147                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5148                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5149                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5150         }
5151
5152         // _norm is the name used by tenebrae and has been adopted as standard
5153         if (r_loadnormalmap && skinframe->nmap == NULL)
5154         {
5155                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false)) != NULL)
5156                 {
5157                         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);
5158                         Mem_Free(pixels);
5159                         pixels = NULL;
5160                 }
5161                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false)) != NULL)
5162                 {
5163                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5164                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5165                         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);
5166                         Mem_Free(pixels);
5167                         Mem_Free(bumppixels);
5168                 }
5169                 else if (r_shadow_bumpscale_basetexture.value > 0)
5170                 {
5171                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5172                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5173                         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);
5174                         Mem_Free(pixels);
5175                 }
5176                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5177                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5178         }
5179
5180         // _luma is supported only for tenebrae compatibility
5181         // _glow is the preferred name
5182         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false))))
5183         {
5184                 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);
5185                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5186                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5187                 Mem_Free(pixels);pixels = NULL;
5188         }
5189
5190         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false)))
5191         {
5192                 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);
5193                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5194                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5195                 Mem_Free(pixels);
5196                 pixels = NULL;
5197         }
5198
5199         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false)))
5200         {
5201                 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);
5202                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5203                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5204                 Mem_Free(pixels);
5205                 pixels = NULL;
5206         }
5207
5208         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false)))
5209         {
5210                 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);
5211                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5212                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5213                 Mem_Free(pixels);
5214                 pixels = NULL;
5215         }
5216
5217         if (basepixels)
5218                 Mem_Free(basepixels);
5219
5220         return skinframe;
5221 }
5222
5223 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5224 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5225 {
5226         int i;
5227         unsigned char *temp1, *temp2;
5228         skinframe_t *skinframe;
5229
5230         if (cls.state == ca_dedicated)
5231                 return NULL;
5232
5233         // if already loaded just return it, otherwise make a new skinframe
5234         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5235         if (skinframe && skinframe->base)
5236                 return skinframe;
5237
5238         skinframe->stain = NULL;
5239         skinframe->merged = NULL;
5240         skinframe->base = NULL;
5241         skinframe->pants = NULL;
5242         skinframe->shirt = NULL;
5243         skinframe->nmap = NULL;
5244         skinframe->gloss = NULL;
5245         skinframe->glow = NULL;
5246         skinframe->fog = NULL;
5247         skinframe->hasalpha = false;
5248
5249         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5250         if (!skindata)
5251                 return NULL;
5252
5253         if (developer_loading.integer)
5254                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5255
5256         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5257         {
5258                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5259                 temp2 = temp1 + width * height * 4;
5260                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5261                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5262                 Mem_Free(temp1);
5263         }
5264         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5265         if (textureflags & TEXF_ALPHA)
5266         {
5267                 for (i = 3;i < width * height * 4;i += 4)
5268                 {
5269                         if (skindata[i] < 255)
5270                         {
5271                                 skinframe->hasalpha = true;
5272                                 break;
5273                         }
5274                 }
5275                 if (r_loadfog && skinframe->hasalpha)
5276                 {
5277                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5278                         memcpy(fogpixels, skindata, width * height * 4);
5279                         for (i = 0;i < width * height * 4;i += 4)
5280                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5281                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5282                         Mem_Free(fogpixels);
5283                 }
5284         }
5285
5286         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5287         //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]);
5288
5289         return skinframe;
5290 }
5291
5292 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5293 {
5294         int i;
5295         int featuresmask;
5296         skinframe_t *skinframe;
5297
5298         if (cls.state == ca_dedicated)
5299                 return NULL;
5300
5301         // if already loaded just return it, otherwise make a new skinframe
5302         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5303         if (skinframe && skinframe->base)
5304                 return skinframe;
5305
5306         skinframe->stain = NULL;
5307         skinframe->merged = NULL;
5308         skinframe->base = NULL;
5309         skinframe->pants = NULL;
5310         skinframe->shirt = NULL;
5311         skinframe->nmap = NULL;
5312         skinframe->gloss = NULL;
5313         skinframe->glow = NULL;
5314         skinframe->fog = NULL;
5315         skinframe->hasalpha = false;
5316
5317         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5318         if (!skindata)
5319                 return NULL;
5320
5321         if (developer_loading.integer)
5322                 Con_Printf("loading quake skin \"%s\"\n", name);
5323
5324         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
5325         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5326         memcpy(skinframe->qpixels, skindata, width*height);
5327         skinframe->qwidth = width;
5328         skinframe->qheight = height;
5329
5330         featuresmask = 0;
5331         for (i = 0;i < width * height;i++)
5332                 featuresmask |= palette_featureflags[skindata[i]];
5333
5334         skinframe->hasalpha = false;
5335         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5336         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5337         skinframe->qgeneratemerged = true;
5338         skinframe->qgeneratebase = skinframe->qhascolormapping;
5339         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5340
5341         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5342         //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]);
5343
5344         return skinframe;
5345 }
5346
5347 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5348 {
5349         int width;
5350         int height;
5351         unsigned char *skindata;
5352
5353         if (!skinframe->qpixels)
5354                 return;
5355
5356         if (!skinframe->qhascolormapping)
5357                 colormapped = false;
5358
5359         if (colormapped)
5360         {
5361                 if (!skinframe->qgeneratebase)
5362                         return;
5363         }
5364         else
5365         {
5366                 if (!skinframe->qgeneratemerged)
5367                         return;
5368         }
5369
5370         width = skinframe->qwidth;
5371         height = skinframe->qheight;
5372         skindata = skinframe->qpixels;
5373
5374         if (skinframe->qgeneratenmap)
5375         {
5376                 unsigned char *temp1, *temp2;
5377                 skinframe->qgeneratenmap = false;
5378                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5379                 temp2 = temp1 + width * height * 4;
5380                 // use either a custom palette or the quake palette
5381                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5382                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5383                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5384                 Mem_Free(temp1);
5385         }
5386
5387         if (skinframe->qgenerateglow)
5388         {
5389                 skinframe->qgenerateglow = false;
5390                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5391         }
5392
5393         if (colormapped)
5394         {
5395                 skinframe->qgeneratebase = false;
5396                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5397                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5398                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5399         }
5400         else
5401         {
5402                 skinframe->qgeneratemerged = false;
5403                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5404         }
5405
5406         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5407         {
5408                 Mem_Free(skinframe->qpixels);
5409                 skinframe->qpixels = NULL;
5410         }
5411 }
5412
5413 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
5414 {
5415         int i;
5416         skinframe_t *skinframe;
5417
5418         if (cls.state == ca_dedicated)
5419                 return NULL;
5420
5421         // if already loaded just return it, otherwise make a new skinframe
5422         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5423         if (skinframe && skinframe->base)
5424                 return skinframe;
5425
5426         skinframe->stain = NULL;
5427         skinframe->merged = NULL;
5428         skinframe->base = NULL;
5429         skinframe->pants = NULL;
5430         skinframe->shirt = NULL;
5431         skinframe->nmap = NULL;
5432         skinframe->gloss = NULL;
5433         skinframe->glow = NULL;
5434         skinframe->fog = NULL;
5435         skinframe->hasalpha = false;
5436
5437         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5438         if (!skindata)
5439                 return NULL;
5440
5441         if (developer_loading.integer)
5442                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5443
5444         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5445         if (textureflags & TEXF_ALPHA)
5446         {
5447                 for (i = 0;i < width * height;i++)
5448                 {
5449                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5450                         {
5451                                 skinframe->hasalpha = true;
5452                                 break;
5453                         }
5454                 }
5455                 if (r_loadfog && skinframe->hasalpha)
5456                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5457         }
5458
5459         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5460         //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]);
5461
5462         return skinframe;
5463 }
5464
5465 skinframe_t *R_SkinFrame_LoadMissing(void)
5466 {
5467         skinframe_t *skinframe;
5468
5469         if (cls.state == ca_dedicated)
5470                 return NULL;
5471
5472         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5473         skinframe->stain = NULL;
5474         skinframe->merged = NULL;
5475         skinframe->base = NULL;
5476         skinframe->pants = NULL;
5477         skinframe->shirt = NULL;
5478         skinframe->nmap = NULL;
5479         skinframe->gloss = NULL;
5480         skinframe->glow = NULL;
5481         skinframe->fog = NULL;
5482         skinframe->hasalpha = false;
5483
5484         skinframe->avgcolor[0] = rand() / RAND_MAX;
5485         skinframe->avgcolor[1] = rand() / RAND_MAX;
5486         skinframe->avgcolor[2] = rand() / RAND_MAX;
5487         skinframe->avgcolor[3] = 1;
5488
5489         return skinframe;
5490 }
5491
5492 void R_Main_FreeViewCache(void)
5493 {
5494         if (r_refdef.viewcache.entityvisible)
5495                 Mem_Free(r_refdef.viewcache.entityvisible);
5496         if (r_refdef.viewcache.world_pvsbits)
5497                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5498         if (r_refdef.viewcache.world_leafvisible)
5499                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5500         if (r_refdef.viewcache.world_surfacevisible)
5501                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5502         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5503 }
5504
5505 void R_Main_ResizeViewCache(void)
5506 {
5507         int numentities = r_refdef.scene.numentities;
5508         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5509         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5510         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5511         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
5512         if (r_refdef.viewcache.maxentities < numentities)
5513         {
5514                 r_refdef.viewcache.maxentities = numentities;
5515                 if (r_refdef.viewcache.entityvisible)
5516                         Mem_Free(r_refdef.viewcache.entityvisible);
5517                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
5518         }
5519         if (r_refdef.viewcache.world_numclusters != numclusters)
5520         {
5521                 r_refdef.viewcache.world_numclusters = numclusters;
5522                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
5523                 if (r_refdef.viewcache.world_pvsbits)
5524                         Mem_Free(r_refdef.viewcache.world_pvsbits);
5525                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
5526         }
5527         if (r_refdef.viewcache.world_numleafs != numleafs)
5528         {
5529                 r_refdef.viewcache.world_numleafs = numleafs;
5530                 if (r_refdef.viewcache.world_leafvisible)
5531                         Mem_Free(r_refdef.viewcache.world_leafvisible);
5532                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
5533         }
5534         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
5535         {
5536                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
5537                 if (r_refdef.viewcache.world_surfacevisible)
5538                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
5539                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
5540         }
5541 }
5542
5543 extern rtexture_t *loadingscreentexture;
5544 void gl_main_start(void)
5545 {
5546         loadingscreentexture = NULL;
5547         r_texture_blanknormalmap = NULL;
5548         r_texture_white = NULL;
5549         r_texture_grey128 = NULL;
5550         r_texture_black = NULL;
5551         r_texture_whitecube = NULL;
5552         r_texture_normalizationcube = NULL;
5553         r_texture_fogattenuation = NULL;
5554         r_texture_gammaramps = NULL;
5555
5556         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
5557         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
5558
5559         switch(vid.renderpath)
5560         {
5561         case RENDERPATH_GL20:
5562         case RENDERPATH_CGGL:
5563                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5564                 Cvar_SetValueQuick(&gl_combine, 1);
5565                 Cvar_SetValueQuick(&r_glsl, 1);
5566                 r_loadnormalmap = true;
5567                 r_loadgloss = true;
5568                 r_loadfog = false;
5569                 break;
5570         case RENDERPATH_GL13:
5571                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5572                 Cvar_SetValueQuick(&gl_combine, 1);
5573                 Cvar_SetValueQuick(&r_glsl, 0);
5574                 r_loadnormalmap = false;
5575                 r_loadgloss = false;
5576                 r_loadfog = true;
5577                 break;
5578         case RENDERPATH_GL11:
5579                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
5580                 Cvar_SetValueQuick(&gl_combine, 0);
5581                 Cvar_SetValueQuick(&r_glsl, 0);
5582                 r_loadnormalmap = false;
5583                 r_loadgloss = false;
5584                 r_loadfog = true;
5585                 break;
5586         }
5587
5588         R_AnimCache_Free();
5589         R_FrameData_Reset();
5590
5591         r_numqueries = 0;
5592         r_maxqueries = 0;
5593         memset(r_queries, 0, sizeof(r_queries));
5594
5595         r_qwskincache = NULL;
5596         r_qwskincache_size = 0;
5597
5598         // set up r_skinframe loading system for textures
5599         memset(&r_skinframe, 0, sizeof(r_skinframe));
5600         r_skinframe.loadsequence = 1;
5601         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
5602
5603         r_main_texturepool = R_AllocTexturePool();
5604         R_BuildBlankTextures();
5605         R_BuildNoTexture();
5606         if (vid.support.arb_texture_cube_map)
5607         {
5608                 R_BuildWhiteCube();
5609                 R_BuildNormalizationCube();
5610         }
5611         r_texture_fogattenuation = NULL;
5612         r_texture_gammaramps = NULL;
5613         //r_texture_fogintensity = NULL;
5614         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5615         memset(&r_waterstate, 0, sizeof(r_waterstate));
5616         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5617         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
5618 #ifdef SUPPORTCG
5619         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5620         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
5621 #endif
5622         memset(&r_svbsp, 0, sizeof (r_svbsp));
5623
5624         r_refdef.fogmasktable_density = 0;
5625 }
5626
5627 void gl_main_shutdown(void)
5628 {
5629         R_AnimCache_Free();
5630         R_FrameData_Reset();
5631
5632         R_Main_FreeViewCache();
5633
5634         if (r_maxqueries)
5635                 qglDeleteQueriesARB(r_maxqueries, r_queries);
5636
5637         r_numqueries = 0;
5638         r_maxqueries = 0;
5639         memset(r_queries, 0, sizeof(r_queries));
5640
5641         r_qwskincache = NULL;
5642         r_qwskincache_size = 0;
5643
5644         // clear out the r_skinframe state
5645         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
5646         memset(&r_skinframe, 0, sizeof(r_skinframe));
5647
5648         if (r_svbsp.nodes)
5649                 Mem_Free(r_svbsp.nodes);
5650         memset(&r_svbsp, 0, sizeof (r_svbsp));
5651         R_FreeTexturePool(&r_main_texturepool);
5652         loadingscreentexture = NULL;
5653         r_texture_blanknormalmap = NULL;
5654         r_texture_white = NULL;
5655         r_texture_grey128 = NULL;
5656         r_texture_black = NULL;
5657         r_texture_whitecube = NULL;
5658         r_texture_normalizationcube = NULL;
5659         r_texture_fogattenuation = NULL;
5660         r_texture_gammaramps = NULL;
5661         //r_texture_fogintensity = NULL;
5662         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
5663         memset(&r_waterstate, 0, sizeof(r_waterstate));
5664         R_GLSL_Restart_f();
5665 }
5666
5667 extern void CL_ParseEntityLump(char *entitystring);
5668 void gl_main_newmap(void)
5669 {
5670         // FIXME: move this code to client
5671         int l;
5672         char *entities, entname[MAX_QPATH];
5673         if (r_qwskincache)
5674                 Mem_Free(r_qwskincache);
5675         r_qwskincache = NULL;
5676         r_qwskincache_size = 0;
5677         if (cl.worldmodel)
5678         {
5679                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
5680                 l = (int)strlen(entname) - 4;
5681                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
5682                 {
5683                         memcpy(entname + l, ".ent", 5);
5684                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
5685                         {
5686                                 CL_ParseEntityLump(entities);
5687                                 Mem_Free(entities);
5688                                 return;
5689                         }
5690                 }
5691                 if (cl.worldmodel->brush.entities)
5692                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
5693         }
5694         R_Main_FreeViewCache();
5695
5696         R_FrameData_Reset();
5697 }
5698
5699 void GL_Main_Init(void)
5700 {
5701         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
5702
5703         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
5704         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
5705         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
5706         if (gamemode == GAME_NEHAHRA)
5707         {
5708                 Cvar_RegisterVariable (&gl_fogenable);
5709                 Cvar_RegisterVariable (&gl_fogdensity);
5710                 Cvar_RegisterVariable (&gl_fogred);
5711                 Cvar_RegisterVariable (&gl_foggreen);
5712                 Cvar_RegisterVariable (&gl_fogblue);
5713                 Cvar_RegisterVariable (&gl_fogstart);
5714                 Cvar_RegisterVariable (&gl_fogend);
5715                 Cvar_RegisterVariable (&gl_skyclip);
5716         }
5717         Cvar_RegisterVariable(&r_motionblur);
5718         Cvar_RegisterVariable(&r_motionblur_maxblur);
5719         Cvar_RegisterVariable(&r_motionblur_bmin);
5720         Cvar_RegisterVariable(&r_motionblur_vmin);
5721         Cvar_RegisterVariable(&r_motionblur_vmax);
5722         Cvar_RegisterVariable(&r_motionblur_vcoeff);
5723         Cvar_RegisterVariable(&r_motionblur_randomize);
5724         Cvar_RegisterVariable(&r_damageblur);
5725         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
5726         Cvar_RegisterVariable(&r_equalize_entities_minambient);
5727         Cvar_RegisterVariable(&r_equalize_entities_by);
5728         Cvar_RegisterVariable(&r_equalize_entities_to);
5729         Cvar_RegisterVariable(&r_depthfirst);
5730         Cvar_RegisterVariable(&r_useinfinitefarclip);
5731         Cvar_RegisterVariable(&r_farclip_base);
5732         Cvar_RegisterVariable(&r_farclip_world);
5733         Cvar_RegisterVariable(&r_nearclip);
5734         Cvar_RegisterVariable(&r_showbboxes);
5735         Cvar_RegisterVariable(&r_showsurfaces);
5736         Cvar_RegisterVariable(&r_showtris);
5737         Cvar_RegisterVariable(&r_shownormals);
5738         Cvar_RegisterVariable(&r_showlighting);
5739         Cvar_RegisterVariable(&r_showshadowvolumes);
5740         Cvar_RegisterVariable(&r_showcollisionbrushes);
5741         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
5742         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
5743         Cvar_RegisterVariable(&r_showdisabledepthtest);
5744         Cvar_RegisterVariable(&r_drawportals);
5745         Cvar_RegisterVariable(&r_drawentities);
5746         Cvar_RegisterVariable(&r_cullentities_trace);
5747         Cvar_RegisterVariable(&r_cullentities_trace_samples);
5748         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
5749         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
5750         Cvar_RegisterVariable(&r_cullentities_trace_delay);
5751         Cvar_RegisterVariable(&r_drawviewmodel);
5752         Cvar_RegisterVariable(&r_speeds);
5753         Cvar_RegisterVariable(&r_fullbrights);
5754         Cvar_RegisterVariable(&r_wateralpha);
5755         Cvar_RegisterVariable(&r_dynamic);
5756         Cvar_RegisterVariable(&r_fullbright);
5757         Cvar_RegisterVariable(&r_shadows);
5758         Cvar_RegisterVariable(&r_shadows_darken);
5759         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
5760         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
5761         Cvar_RegisterVariable(&r_shadows_throwdistance);
5762         Cvar_RegisterVariable(&r_shadows_throwdirection);
5763         Cvar_RegisterVariable(&r_q1bsp_skymasking);
5764         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
5765         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
5766         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
5767         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
5768         Cvar_RegisterVariable(&r_fog_exp2);
5769         Cvar_RegisterVariable(&r_drawfog);
5770         Cvar_RegisterVariable(&r_transparentdepthmasking);
5771         Cvar_RegisterVariable(&r_texture_dds_load);
5772         Cvar_RegisterVariable(&r_texture_dds_save);
5773         Cvar_RegisterVariable(&r_textureunits);
5774         Cvar_RegisterVariable(&gl_combine);
5775         Cvar_RegisterVariable(&r_glsl);
5776         Cvar_RegisterVariable(&r_glsl_deluxemapping);
5777         Cvar_RegisterVariable(&r_glsl_offsetmapping);
5778         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
5779         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
5780         Cvar_RegisterVariable(&r_glsl_postprocess);
5781         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
5782         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
5783         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
5784         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
5785         Cvar_RegisterVariable(&r_water);
5786         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
5787         Cvar_RegisterVariable(&r_water_clippingplanebias);
5788         Cvar_RegisterVariable(&r_water_refractdistort);
5789         Cvar_RegisterVariable(&r_water_reflectdistort);
5790         Cvar_RegisterVariable(&r_lerpsprites);
5791         Cvar_RegisterVariable(&r_lerpmodels);
5792         Cvar_RegisterVariable(&r_lerplightstyles);
5793         Cvar_RegisterVariable(&r_waterscroll);
5794         Cvar_RegisterVariable(&r_bloom);
5795         Cvar_RegisterVariable(&r_bloom_colorscale);
5796         Cvar_RegisterVariable(&r_bloom_brighten);
5797         Cvar_RegisterVariable(&r_bloom_blur);
5798         Cvar_RegisterVariable(&r_bloom_resolution);
5799         Cvar_RegisterVariable(&r_bloom_colorexponent);
5800         Cvar_RegisterVariable(&r_bloom_colorsubtract);
5801         Cvar_RegisterVariable(&r_hdr);
5802         Cvar_RegisterVariable(&r_hdr_scenebrightness);
5803         Cvar_RegisterVariable(&r_hdr_glowintensity);
5804         Cvar_RegisterVariable(&r_hdr_range);
5805         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
5806         Cvar_RegisterVariable(&developer_texturelogging);
5807         Cvar_RegisterVariable(&gl_lightmaps);
5808         Cvar_RegisterVariable(&r_test);
5809         Cvar_RegisterVariable(&r_batchmode);
5810         Cvar_RegisterVariable(&r_glsl_saturation);
5811         Cvar_RegisterVariable(&r_framedatasize);
5812         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
5813                 Cvar_SetValue("r_fullbrights", 0);
5814         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
5815
5816         Cvar_RegisterVariable(&r_track_sprites);
5817         Cvar_RegisterVariable(&r_track_sprites_flags);
5818         Cvar_RegisterVariable(&r_track_sprites_scalew);
5819         Cvar_RegisterVariable(&r_track_sprites_scaleh);
5820 }
5821
5822 extern void R_Textures_Init(void);
5823 extern void GL_Draw_Init(void);
5824 extern void GL_Main_Init(void);
5825 extern void R_Shadow_Init(void);
5826 extern void R_Sky_Init(void);
5827 extern void GL_Surf_Init(void);
5828 extern void R_Particles_Init(void);
5829 extern void R_Explosion_Init(void);
5830 extern void gl_backend_init(void);
5831 extern void Sbar_Init(void);
5832 extern void R_LightningBeams_Init(void);
5833 extern void Mod_RenderInit(void);
5834 extern void Font_Init(void);
5835
5836 void Render_Init(void)
5837 {
5838         gl_backend_init();
5839         R_Textures_Init();
5840         GL_Main_Init();
5841         Font_Init();
5842         GL_Draw_Init();
5843         R_Shadow_Init();
5844         R_Sky_Init();
5845         GL_Surf_Init();
5846         Sbar_Init();
5847         R_Particles_Init();
5848         R_Explosion_Init();
5849         R_LightningBeams_Init();
5850         Mod_RenderInit();
5851 }
5852
5853 /*
5854 ===============
5855 GL_Init
5856 ===============
5857 */
5858 extern char *ENGINE_EXTENSIONS;
5859 void GL_Init (void)
5860 {
5861         gl_renderer = (const char *)qglGetString(GL_RENDERER);
5862         gl_vendor = (const char *)qglGetString(GL_VENDOR);
5863         gl_version = (const char *)qglGetString(GL_VERSION);
5864         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
5865
5866         if (!gl_extensions)
5867                 gl_extensions = "";
5868         if (!gl_platformextensions)
5869                 gl_platformextensions = "";
5870
5871         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
5872         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
5873         Con_Printf("GL_VERSION: %s\n", gl_version);
5874         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
5875         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
5876
5877         VID_CheckExtensions();
5878
5879         // LordHavoc: report supported extensions
5880         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
5881
5882         // clear to black (loading plaque will be seen over this)
5883         CHECKGLERROR
5884         qglClearColor(0,0,0,1);CHECKGLERROR
5885         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
5886 }
5887
5888 int R_CullBox(const vec3_t mins, const vec3_t maxs)
5889 {
5890         int i;
5891         mplane_t *p;
5892         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5893         {
5894                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
5895                 if (i == 4)
5896                         continue;
5897                 p = r_refdef.view.frustum + i;
5898                 switch(p->signbits)
5899                 {
5900                 default:
5901                 case 0:
5902                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5903                                 return true;
5904                         break;
5905                 case 1:
5906                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5907                                 return true;
5908                         break;
5909                 case 2:
5910                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5911                                 return true;
5912                         break;
5913                 case 3:
5914                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5915                                 return true;
5916                         break;
5917                 case 4:
5918                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5919                                 return true;
5920                         break;
5921                 case 5:
5922                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5923                                 return true;
5924                         break;
5925                 case 6:
5926                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5927                                 return true;
5928                         break;
5929                 case 7:
5930                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5931                                 return true;
5932                         break;
5933                 }
5934         }
5935         return false;
5936 }
5937
5938 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
5939 {
5940         int i;
5941         const mplane_t *p;
5942         for (i = 0;i < numplanes;i++)
5943         {
5944                 p = planes + i;
5945                 switch(p->signbits)
5946                 {
5947                 default:
5948                 case 0:
5949                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5950                                 return true;
5951                         break;
5952                 case 1:
5953                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
5954                                 return true;
5955                         break;
5956                 case 2:
5957                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5958                                 return true;
5959                         break;
5960                 case 3:
5961                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
5962                                 return true;
5963                         break;
5964                 case 4:
5965                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5966                                 return true;
5967                         break;
5968                 case 5:
5969                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
5970                                 return true;
5971                         break;
5972                 case 6:
5973                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5974                                 return true;
5975                         break;
5976                 case 7:
5977                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
5978                                 return true;
5979                         break;
5980                 }
5981         }
5982         return false;
5983 }
5984
5985 //==================================================================================
5986
5987 // LordHavoc: this stores temporary data used within the same frame
5988
5989 qboolean r_framedata_failed;
5990 static size_t r_framedata_size;
5991 static size_t r_framedata_current;
5992 static void *r_framedata_base;
5993
5994 void R_FrameData_Reset(void)
5995 {
5996         if (r_framedata_base)
5997                 Mem_Free(r_framedata_base);
5998         r_framedata_base = NULL;
5999         r_framedata_size = 0;
6000         r_framedata_current = 0;
6001         r_framedata_failed = false;
6002 }
6003
6004 void R_FrameData_NewFrame(void)
6005 {
6006         size_t wantedsize;
6007         if (r_framedata_failed)
6008                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6009         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6010         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6011         if (r_framedata_size != wantedsize)
6012         {
6013                 r_framedata_size = wantedsize;
6014                 if (r_framedata_base)
6015                         Mem_Free(r_framedata_base);
6016                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6017         }
6018         r_framedata_current = 0;
6019         r_framedata_failed = false;
6020 }
6021
6022 void *R_FrameData_Alloc(size_t size)
6023 {
6024         void *data;
6025
6026         // align to 16 byte boundary
6027         size = (size + 15) & ~15;
6028         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6029         r_framedata_current += size;
6030
6031         // check overflow
6032         if (r_framedata_current > r_framedata_size)
6033                 r_framedata_failed = true;
6034
6035         // return NULL on everything after a failure
6036         if (r_framedata_failed)
6037                 return NULL;
6038
6039         return data;
6040 }
6041
6042 void *R_FrameData_Store(size_t size, void *data)
6043 {
6044         void *d = R_FrameData_Alloc(size);
6045         if (d)
6046                 memcpy(d, data, size);
6047         return d;
6048 }
6049
6050 //==================================================================================
6051
6052 // LordHavoc: animcache originally written by Echon, rewritten since then
6053
6054 /**
6055  * Animation cache prevents re-generating mesh data for an animated model
6056  * multiple times in one frame for lighting, shadowing, reflections, etc.
6057  */
6058
6059 void R_AnimCache_Free(void)
6060 {
6061 }
6062
6063 void R_AnimCache_ClearCache(void)
6064 {
6065         int i;
6066         entity_render_t *ent;
6067
6068         for (i = 0;i < r_refdef.scene.numentities;i++)
6069         {
6070                 ent = r_refdef.scene.entities[i];
6071                 ent->animcache_vertex3f = NULL;
6072                 ent->animcache_normal3f = NULL;
6073                 ent->animcache_svector3f = NULL;
6074                 ent->animcache_tvector3f = NULL;
6075         }
6076 }
6077
6078 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6079 {
6080         dp_model_t *model = ent->model;
6081         int numvertices;
6082         // see if it's already cached this frame
6083         if (ent->animcache_vertex3f)
6084         {
6085                 // add normals/tangents if needed
6086                 if (wantnormals || wanttangents)
6087                 {
6088                         if (ent->animcache_normal3f)
6089                                 wantnormals = false;
6090                         if (ent->animcache_svector3f)
6091                                 wanttangents = false;
6092                         if (wantnormals || wanttangents)
6093                         {
6094                                 numvertices = model->surfmesh.num_vertices;
6095                                 if (wantnormals)
6096                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6097                                 if (wanttangents)
6098                                 {
6099                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6100                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6101                                 }
6102                                 if (!r_framedata_failed)
6103                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6104                         }
6105                 }
6106         }
6107         else
6108         {
6109                 // see if this ent is worth caching
6110                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6111                         return false;
6112                 // get some memory for this entity and generate mesh data
6113                 numvertices = model->surfmesh.num_vertices;
6114                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6115                 if (wantnormals)
6116                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6117                 if (wanttangents)
6118                 {
6119                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6120                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6121                 }
6122                 if (!r_framedata_failed)
6123                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6124         }
6125         return !r_framedata_failed;
6126 }
6127
6128 void R_AnimCache_CacheVisibleEntities(void)
6129 {
6130         int i;
6131         qboolean wantnormals = !r_showsurfaces.integer;
6132         qboolean wanttangents = !r_showsurfaces.integer;
6133
6134         switch(vid.renderpath)
6135         {
6136         case RENDERPATH_GL20:
6137         case RENDERPATH_CGGL:
6138                 break;
6139         case RENDERPATH_GL13:
6140         case RENDERPATH_GL11:
6141                 wanttangents = false;
6142                 break;
6143         }
6144
6145         // TODO: thread this
6146         // NOTE: R_PrepareRTLights() also caches entities
6147
6148         for (i = 0;i < r_refdef.scene.numentities;i++)
6149                 if (r_refdef.viewcache.entityvisible[i])
6150                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6151
6152         if (r_shadows.integer)
6153                 for (i = 0;i < r_refdef.scene.numentities;i++)
6154                         if (!r_refdef.viewcache.entityvisible[i])
6155                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6156 }
6157
6158 //==================================================================================
6159
6160 static void R_View_UpdateEntityLighting (void)
6161 {
6162         int i;
6163         entity_render_t *ent;
6164         vec3_t tempdiffusenormal, avg;
6165         vec_t f, fa, fd, fdd;
6166
6167         for (i = 0;i < r_refdef.scene.numentities;i++)
6168         {
6169                 ent = r_refdef.scene.entities[i];
6170
6171                 // skip unseen models
6172                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6173                         continue;
6174
6175                 // skip bsp models
6176                 if (ent->model && ent->model->brush.num_leafs)
6177                 {
6178                         // TODO: use modellight for r_ambient settings on world?
6179                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6180                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6181                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6182                         continue;
6183                 }
6184
6185                 // fetch the lighting from the worldmodel data
6186                 VectorClear(ent->modellight_ambient);
6187                 VectorClear(ent->modellight_diffuse);
6188                 VectorClear(tempdiffusenormal);
6189                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6190                 {
6191                         vec3_t org;
6192                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6193                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6194                         if(ent->flags & RENDER_EQUALIZE)
6195                         {
6196                                 // first fix up ambient lighting...
6197                                 if(r_equalize_entities_minambient.value > 0)
6198                                 {
6199                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6200                                         if(fd > 0)
6201                                         {
6202                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6203                                                 if(fa < r_equalize_entities_minambient.value * fd)
6204                                                 {
6205                                                         // solve:
6206                                                         //   fa'/fd' = minambient
6207                                                         //   fa'+0.25*fd' = fa+0.25*fd
6208                                                         //   ...
6209                                                         //   fa' = fd' * minambient
6210                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6211                                                         //   ...
6212                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6213                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6214                                                         //   ...
6215                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6216                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
6217                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6218                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6219                                                 }
6220                                         }
6221                                 }
6222
6223                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6224                                 {
6225                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6226                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6227                                         if(f > 0)
6228                                         {
6229                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6230                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6231                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6232                                         }
6233                                 }
6234                         }
6235                 }
6236                 else // highly rare
6237                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6238
6239                 // move the light direction into modelspace coordinates for lighting code
6240                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6241                 if(VectorLength2(ent->modellight_lightdir) == 0)
6242                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6243                 VectorNormalize(ent->modellight_lightdir);
6244         }
6245 }
6246
6247 #define MAX_LINEOFSIGHTTRACES 64
6248
6249 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6250 {
6251         int i;
6252         vec3_t boxmins, boxmaxs;
6253         vec3_t start;
6254         vec3_t end;
6255         dp_model_t *model = r_refdef.scene.worldmodel;
6256
6257         if (!model || !model->brush.TraceLineOfSight)
6258                 return true;
6259
6260         // expand the box a little
6261         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6262         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6263         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6264         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6265         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6266         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6267
6268         // try center
6269         VectorCopy(eye, start);
6270         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6271         if (model->brush.TraceLineOfSight(model, start, end))
6272                 return true;
6273
6274         // try various random positions
6275         for (i = 0;i < numsamples;i++)
6276         {
6277                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6278                 if (model->brush.TraceLineOfSight(model, start, end))
6279                         return true;
6280         }
6281
6282         return false;
6283 }
6284
6285
6286 static void R_View_UpdateEntityVisible (void)
6287 {
6288         int i;
6289         int renderimask;
6290         int samples;
6291         entity_render_t *ent;
6292
6293         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6294         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6295         {
6296                 // worldmodel can check visibility
6297                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6298                 for (i = 0;i < r_refdef.scene.numentities;i++)
6299                 {
6300                         ent = r_refdef.scene.entities[i];
6301                         if (!(ent->flags & renderimask))
6302                         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)))
6303                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
6304                                 r_refdef.viewcache.entityvisible[i] = true;
6305                 }
6306                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6307                 {
6308                         for (i = 0;i < r_refdef.scene.numentities;i++)
6309                         {
6310                                 ent = r_refdef.scene.entities[i];
6311                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6312                                 {
6313                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6314                                         if (samples < 0)
6315                                                 continue; // temp entities do pvs only
6316                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6317                                                 ent->last_trace_visibility = realtime;
6318                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6319                                                 r_refdef.viewcache.entityvisible[i] = 0;
6320                                 }
6321                         }
6322                 }
6323         }
6324         else
6325         {
6326                 // no worldmodel or it can't check visibility
6327                 for (i = 0;i < r_refdef.scene.numentities;i++)
6328                 {
6329                         ent = r_refdef.scene.entities[i];
6330                         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));
6331                 }
6332         }
6333 }
6334
6335 /// only used if skyrendermasked, and normally returns false
6336 int R_DrawBrushModelsSky (void)
6337 {
6338         int i, sky;
6339         entity_render_t *ent;
6340
6341         sky = false;
6342         for (i = 0;i < r_refdef.scene.numentities;i++)
6343         {
6344                 if (!r_refdef.viewcache.entityvisible[i])
6345                         continue;
6346                 ent = r_refdef.scene.entities[i];
6347                 if (!ent->model || !ent->model->DrawSky)
6348                         continue;
6349                 ent->model->DrawSky(ent);
6350                 sky = true;
6351         }
6352         return sky;
6353 }
6354
6355 static void R_DrawNoModel(entity_render_t *ent);
6356 static void R_DrawModels(void)
6357 {
6358         int i;
6359         entity_render_t *ent;
6360
6361         for (i = 0;i < r_refdef.scene.numentities;i++)
6362         {
6363                 if (!r_refdef.viewcache.entityvisible[i])
6364                         continue;
6365                 ent = r_refdef.scene.entities[i];
6366                 r_refdef.stats.entities++;
6367                 if (ent->model && ent->model->Draw != NULL)
6368                         ent->model->Draw(ent);
6369                 else
6370                         R_DrawNoModel(ent);
6371         }
6372 }
6373
6374 static void R_DrawModelsDepth(void)
6375 {
6376         int i;
6377         entity_render_t *ent;
6378
6379         for (i = 0;i < r_refdef.scene.numentities;i++)
6380         {
6381                 if (!r_refdef.viewcache.entityvisible[i])
6382                         continue;
6383                 ent = r_refdef.scene.entities[i];
6384                 if (ent->model && ent->model->DrawDepth != NULL)
6385                         ent->model->DrawDepth(ent);
6386         }
6387 }
6388
6389 static void R_DrawModelsDebug(void)
6390 {
6391         int i;
6392         entity_render_t *ent;
6393
6394         for (i = 0;i < r_refdef.scene.numentities;i++)
6395         {
6396                 if (!r_refdef.viewcache.entityvisible[i])
6397                         continue;
6398                 ent = r_refdef.scene.entities[i];
6399                 if (ent->model && ent->model->DrawDebug != NULL)
6400                         ent->model->DrawDebug(ent);
6401         }
6402 }
6403
6404 static void R_DrawModelsAddWaterPlanes(void)
6405 {
6406         int i;
6407         entity_render_t *ent;
6408
6409         for (i = 0;i < r_refdef.scene.numentities;i++)
6410         {
6411                 if (!r_refdef.viewcache.entityvisible[i])
6412                         continue;
6413                 ent = r_refdef.scene.entities[i];
6414                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6415                         ent->model->DrawAddWaterPlanes(ent);
6416         }
6417 }
6418
6419 static void R_View_SetFrustum(void)
6420 {
6421         int i;
6422         double slopex, slopey;
6423         vec3_t forward, left, up, origin;
6424
6425         // we can't trust r_refdef.view.forward and friends in reflected scenes
6426         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6427
6428 #if 0
6429         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6430         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6431         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6432         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6433         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6434         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6435         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6436         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6437         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6438         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6439         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6440         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6441 #endif
6442
6443 #if 0
6444         zNear = r_refdef.nearclip;
6445         nudge = 1.0 - 1.0 / (1<<23);
6446         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6447         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6448         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6449         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6450         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6451         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6452         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6453         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6454 #endif
6455
6456
6457
6458 #if 0
6459         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6460         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6461         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6462         r_refdef.view.frustum[0].dist = m[15] - m[12];
6463
6464         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6465         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6466         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6467         r_refdef.view.frustum[1].dist = m[15] + m[12];
6468
6469         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6470         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6471         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6472         r_refdef.view.frustum[2].dist = m[15] - m[13];
6473
6474         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6475         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6476         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6477         r_refdef.view.frustum[3].dist = m[15] + m[13];
6478
6479         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6480         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6481         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6482         r_refdef.view.frustum[4].dist = m[15] - m[14];
6483
6484         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6485         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6486         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6487         r_refdef.view.frustum[5].dist = m[15] + m[14];
6488 #endif
6489
6490         if (r_refdef.view.useperspective)
6491         {
6492                 slopex = 1.0 / r_refdef.view.frustum_x;
6493                 slopey = 1.0 / r_refdef.view.frustum_y;
6494                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6495                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6496                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6497                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
6498                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6499
6500                 // Leaving those out was a mistake, those were in the old code, and they
6501                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
6502                 // I couldn't reproduce it after adding those normalizations. --blub
6503                 VectorNormalize(r_refdef.view.frustum[0].normal);
6504                 VectorNormalize(r_refdef.view.frustum[1].normal);
6505                 VectorNormalize(r_refdef.view.frustum[2].normal);
6506                 VectorNormalize(r_refdef.view.frustum[3].normal);
6507
6508                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
6509                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
6510                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left, -1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
6511                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward, -1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
6512                 VectorMAMAMAM(1, r_refdef.view.origin, 1024, forward,  1024 * r_refdef.view.frustum_x, left,  1024 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
6513
6514                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
6515                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
6516                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
6517                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
6518                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6519         }
6520         else
6521         {
6522                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
6523                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
6524                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
6525                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
6526                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
6527                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
6528                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
6529                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
6530                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
6531                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
6532         }
6533         r_refdef.view.numfrustumplanes = 5;
6534
6535         if (r_refdef.view.useclipplane)
6536         {
6537                 r_refdef.view.numfrustumplanes = 6;
6538                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
6539         }
6540
6541         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6542                 PlaneClassify(r_refdef.view.frustum + i);
6543
6544         // LordHavoc: note to all quake engine coders, Quake had a special case
6545         // for 90 degrees which assumed a square view (wrong), so I removed it,
6546         // Quake2 has it disabled as well.
6547
6548         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
6549         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
6550         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
6551         //PlaneClassify(&frustum[0]);
6552
6553         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
6554         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
6555         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
6556         //PlaneClassify(&frustum[1]);
6557
6558         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
6559         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
6560         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
6561         //PlaneClassify(&frustum[2]);
6562
6563         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
6564         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
6565         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
6566         //PlaneClassify(&frustum[3]);
6567
6568         // nearclip plane
6569         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
6570         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
6571         //PlaneClassify(&frustum[4]);
6572 }
6573
6574 void R_View_Update(void)
6575 {
6576         R_Main_ResizeViewCache();
6577         R_View_SetFrustum();
6578         R_View_WorldVisibility(r_refdef.view.useclipplane);
6579         R_View_UpdateEntityVisible();
6580         R_View_UpdateEntityLighting();
6581 }
6582
6583 void R_SetupView(qboolean allowwaterclippingplane)
6584 {
6585         const float *customclipplane = NULL;
6586         float plane[4];
6587         if (r_refdef.view.useclipplane && allowwaterclippingplane)
6588         {
6589                 // LordHavoc: couldn't figure out how to make this approach the
6590                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
6591                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
6592                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
6593                         dist = r_refdef.view.clipplane.dist;
6594                 plane[0] = r_refdef.view.clipplane.normal[0];
6595                 plane[1] = r_refdef.view.clipplane.normal[1];
6596                 plane[2] = r_refdef.view.clipplane.normal[2];
6597                 plane[3] = dist;
6598                 customclipplane = plane;
6599         }
6600
6601         if (!r_refdef.view.useperspective)
6602                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
6603         else if (vid.stencil && r_useinfinitefarclip.integer)
6604                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
6605         else
6606                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
6607         R_SetViewport(&r_refdef.view.viewport);
6608 }
6609
6610 void R_EntityMatrix(const matrix4x4_t *matrix)
6611 {
6612         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
6613         {
6614                 gl_modelmatrixchanged = false;
6615                 gl_modelmatrix = *matrix;
6616                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
6617                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
6618                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
6619                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
6620                 CHECKGLERROR
6621                 switch(vid.renderpath)
6622                 {
6623                 case RENDERPATH_GL20:
6624                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
6625                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
6626                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6627                         break;
6628                 case RENDERPATH_CGGL:
6629 #ifdef SUPPORTCG
6630                         CHECKCGERROR
6631                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
6632                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
6633                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6634 #endif
6635                         break;
6636                 case RENDERPATH_GL13:
6637                 case RENDERPATH_GL11:
6638                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
6639                         break;
6640                 }
6641         }
6642 }
6643
6644 void R_ResetViewRendering2D(void)
6645 {
6646         r_viewport_t viewport;
6647         DrawQ_Finish();
6648
6649         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
6650         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
6651         R_SetViewport(&viewport);
6652         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
6653         GL_Color(1, 1, 1, 1);
6654         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6655         GL_BlendFunc(GL_ONE, GL_ZERO);
6656         GL_AlphaTest(false);
6657         GL_ScissorTest(false);
6658         GL_DepthMask(false);
6659         GL_DepthRange(0, 1);
6660         GL_DepthTest(false);
6661         R_EntityMatrix(&identitymatrix);
6662         R_Mesh_ResetTextureState();
6663         GL_PolygonOffset(0, 0);
6664         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6665         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6666         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6667         qglStencilMask(~0);CHECKGLERROR
6668         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6669         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6670         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
6671 }
6672
6673 void R_ResetViewRendering3D(void)
6674 {
6675         DrawQ_Finish();
6676
6677         R_SetupView(true);
6678         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6679         GL_Color(1, 1, 1, 1);
6680         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
6681         GL_BlendFunc(GL_ONE, GL_ZERO);
6682         GL_AlphaTest(false);
6683         GL_ScissorTest(true);
6684         GL_DepthMask(true);
6685         GL_DepthRange(0, 1);
6686         GL_DepthTest(true);
6687         R_EntityMatrix(&identitymatrix);
6688         R_Mesh_ResetTextureState();
6689         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6690         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
6691         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
6692         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
6693         qglStencilMask(~0);CHECKGLERROR
6694         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
6695         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
6696         GL_CullFace(r_refdef.view.cullface_back);
6697 }
6698
6699 void R_RenderScene(void);
6700 void R_RenderWaterPlanes(void);
6701
6702 static void R_Water_StartFrame(void)
6703 {
6704         int i;
6705         int waterwidth, waterheight, texturewidth, textureheight;
6706         r_waterstate_waterplane_t *p;
6707
6708         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6709                 return;
6710
6711         switch(vid.renderpath)
6712         {
6713         case RENDERPATH_GL20:
6714         case RENDERPATH_CGGL:
6715                 break;
6716         case RENDERPATH_GL13:
6717         case RENDERPATH_GL11:
6718                 return;
6719         }
6720
6721         // set waterwidth and waterheight to the water resolution that will be
6722         // used (often less than the screen resolution for faster rendering)
6723         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
6724         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
6725
6726         // calculate desired texture sizes
6727         // can't use water if the card does not support the texture size
6728         if (!r_water.integer || r_showsurfaces.integer)
6729                 texturewidth = textureheight = waterwidth = waterheight = 0;
6730         else if (vid.support.arb_texture_non_power_of_two)
6731         {
6732                 texturewidth = waterwidth;
6733                 textureheight = waterheight;
6734         }
6735         else
6736         {
6737                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
6738                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
6739         }
6740
6741         // allocate textures as needed
6742         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
6743         {
6744                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6745                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
6746                 {
6747                         if (p->texture_refraction)
6748                                 R_FreeTexture(p->texture_refraction);
6749                         p->texture_refraction = NULL;
6750                         if (p->texture_reflection)
6751                                 R_FreeTexture(p->texture_reflection);
6752                         p->texture_reflection = NULL;
6753                 }
6754                 memset(&r_waterstate, 0, sizeof(r_waterstate));
6755                 r_waterstate.texturewidth = texturewidth;
6756                 r_waterstate.textureheight = textureheight;
6757         }
6758
6759         if (r_waterstate.texturewidth)
6760         {
6761                 r_waterstate.enabled = true;
6762
6763                 // when doing a reduced render (HDR) we want to use a smaller area
6764                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6765                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6766
6767                 // set up variables that will be used in shader setup
6768                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6769                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6770                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
6771                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
6772         }
6773
6774         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
6775         r_waterstate.numwaterplanes = 0;
6776 }
6777
6778 void R_Water_AddWaterPlane(msurface_t *surface)
6779 {
6780         int triangleindex, planeindex;
6781         const int *e;
6782         vec3_t vert[3];
6783         vec3_t normal;
6784         vec3_t center;
6785         mplane_t plane;
6786         r_waterstate_waterplane_t *p;
6787         texture_t *t = R_GetCurrentTexture(surface->texture);
6788         // just use the first triangle with a valid normal for any decisions
6789         VectorClear(normal);
6790         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
6791         {
6792                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
6793                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
6794                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
6795                 TriangleNormal(vert[0], vert[1], vert[2], normal);
6796                 if (VectorLength2(normal) >= 0.001)
6797                         break;
6798         }
6799
6800         VectorCopy(normal, plane.normal);
6801         VectorNormalize(plane.normal);
6802         plane.dist = DotProduct(vert[0], plane.normal);
6803         PlaneClassify(&plane);
6804         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6805         {
6806                 // skip backfaces (except if nocullface is set)
6807                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6808                         return;
6809                 VectorNegate(plane.normal, plane.normal);
6810                 plane.dist *= -1;
6811                 PlaneClassify(&plane);
6812         }
6813
6814
6815         // find a matching plane if there is one
6816         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6817                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
6818                         break;
6819         if (planeindex >= r_waterstate.maxwaterplanes)
6820                 return; // nothing we can do, out of planes
6821
6822         // if this triangle does not fit any known plane rendered this frame, add one
6823         if (planeindex >= r_waterstate.numwaterplanes)
6824         {
6825                 // store the new plane
6826                 r_waterstate.numwaterplanes++;
6827                 p->plane = plane;
6828                 // clear materialflags and pvs
6829                 p->materialflags = 0;
6830                 p->pvsvalid = false;
6831         }
6832         // merge this surface's materialflags into the waterplane
6833         p->materialflags |= t->currentmaterialflags;
6834         // merge this surface's PVS into the waterplane
6835         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
6836         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6837          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6838         {
6839                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6840                 p->pvsvalid = true;
6841         }
6842 }
6843
6844 static void R_Water_ProcessPlanes(void)
6845 {
6846         r_refdef_view_t originalview;
6847         r_refdef_view_t myview;
6848         int planeindex;
6849         r_waterstate_waterplane_t *p;
6850
6851         originalview = r_refdef.view;
6852
6853         // make sure enough textures are allocated
6854         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6855         {
6856                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6857                 {
6858                         if (!p->texture_refraction)
6859                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6860                         if (!p->texture_refraction)
6861                                 goto error;
6862                 }
6863
6864                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6865                 {
6866                         if (!p->texture_reflection)
6867                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
6868                         if (!p->texture_reflection)
6869                                 goto error;
6870                 }
6871         }
6872
6873         // render views
6874         r_refdef.view = originalview;
6875         r_refdef.view.showdebug = false;
6876         r_refdef.view.width = r_waterstate.waterwidth;
6877         r_refdef.view.height = r_waterstate.waterheight;
6878         r_refdef.view.useclipplane = true;
6879         myview = r_refdef.view;
6880         r_waterstate.renderingscene = true;
6881         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
6882         {
6883                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6884                 {
6885                         r_refdef.view = myview;
6886                         // render reflected scene and copy into texture
6887                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6888                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6889                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6890                         r_refdef.view.clipplane = p->plane;
6891                         // reverse the cullface settings for this render
6892                         r_refdef.view.cullface_front = GL_FRONT;
6893                         r_refdef.view.cullface_back = GL_BACK;
6894                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6895                         {
6896                                 r_refdef.view.usecustompvs = true;
6897                                 if (p->pvsvalid)
6898                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6899                                 else
6900                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6901                         }
6902
6903                         R_ResetViewRendering3D();
6904                         R_ClearScreen(r_refdef.fogenabled);
6905                         R_View_Update();
6906                         R_RenderScene();
6907
6908                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6909                 }
6910
6911                 // render the normal view scene and copy into texture
6912                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
6913                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6914                 {
6915                         r_refdef.view = myview;
6916                         r_refdef.view.clipplane = p->plane;
6917                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6918                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6919                         PlaneClassify(&r_refdef.view.clipplane);
6920
6921                         R_ResetViewRendering3D();
6922                         R_ClearScreen(r_refdef.fogenabled);
6923                         R_View_Update();
6924                         R_RenderScene();
6925
6926                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6927                 }
6928
6929         }
6930         r_waterstate.renderingscene = false;
6931         r_refdef.view = originalview;
6932         R_ResetViewRendering3D();
6933         R_ClearScreen(r_refdef.fogenabled);
6934         R_View_Update();
6935         return;
6936 error:
6937         r_refdef.view = originalview;
6938         r_waterstate.renderingscene = false;
6939         Cvar_SetValueQuick(&r_water, 0);
6940         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6941         return;
6942 }
6943
6944 void R_Bloom_StartFrame(void)
6945 {
6946         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6947
6948         switch(vid.renderpath)
6949         {
6950         case RENDERPATH_GL20:
6951         case RENDERPATH_CGGL:
6952                 break;
6953         case RENDERPATH_GL13:
6954         case RENDERPATH_GL11:
6955                 return;
6956         }
6957
6958         // set bloomwidth and bloomheight to the bloom resolution that will be
6959         // used (often less than the screen resolution for faster rendering)
6960         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6961         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6962         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6963         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6964         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6965
6966         // calculate desired texture sizes
6967         if (vid.support.arb_texture_non_power_of_two)
6968         {
6969                 screentexturewidth = r_refdef.view.width;
6970                 screentextureheight = r_refdef.view.height;
6971                 bloomtexturewidth = r_bloomstate.bloomwidth;
6972                 bloomtextureheight = r_bloomstate.bloomheight;
6973         }
6974         else
6975         {
6976                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6977                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6978                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6979                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6980         }
6981
6982         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
6983         {
6984                 Cvar_SetValueQuick(&r_hdr, 0);
6985                 Cvar_SetValueQuick(&r_bloom, 0);
6986                 Cvar_SetValueQuick(&r_motionblur, 0);
6987                 Cvar_SetValueQuick(&r_damageblur, 0);
6988         }
6989
6990         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)))
6991                 screentexturewidth = screentextureheight = 0;
6992         if (!r_hdr.integer && !r_bloom.integer)
6993                 bloomtexturewidth = bloomtextureheight = 0;
6994
6995         // allocate textures as needed
6996         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
6997         {
6998                 if (r_bloomstate.texture_screen)
6999                         R_FreeTexture(r_bloomstate.texture_screen);
7000                 r_bloomstate.texture_screen = NULL;
7001                 r_bloomstate.screentexturewidth = screentexturewidth;
7002                 r_bloomstate.screentextureheight = screentextureheight;
7003                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7004                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7005         }
7006         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7007         {
7008                 if (r_bloomstate.texture_bloom)
7009                         R_FreeTexture(r_bloomstate.texture_bloom);
7010                 r_bloomstate.texture_bloom = NULL;
7011                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7012                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7013                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7014                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7015         }
7016
7017         // when doing a reduced render (HDR) we want to use a smaller area
7018         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7019         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7021         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7022         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7023
7024         // set up a texcoord array for the full resolution screen image
7025         // (we have to keep this around to copy back during final render)
7026         r_bloomstate.screentexcoord2f[0] = 0;
7027         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7028         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7029         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7030         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7031         r_bloomstate.screentexcoord2f[5] = 0;
7032         r_bloomstate.screentexcoord2f[6] = 0;
7033         r_bloomstate.screentexcoord2f[7] = 0;
7034
7035         // set up a texcoord array for the reduced resolution bloom image
7036         // (which will be additive blended over the screen image)
7037         r_bloomstate.bloomtexcoord2f[0] = 0;
7038         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7039         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7040         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7041         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7042         r_bloomstate.bloomtexcoord2f[5] = 0;
7043         r_bloomstate.bloomtexcoord2f[6] = 0;
7044         r_bloomstate.bloomtexcoord2f[7] = 0;
7045
7046         if (r_hdr.integer || r_bloom.integer)
7047         {
7048                 r_bloomstate.enabled = true;
7049                 r_bloomstate.hdr = r_hdr.integer != 0;
7050         }
7051
7052         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
7053 }
7054
7055 void R_Bloom_CopyBloomTexture(float colorscale)
7056 {
7057         r_refdef.stats.bloom++;
7058
7059         // scale down screen texture to the bloom texture size
7060         CHECKGLERROR
7061         R_SetViewport(&r_bloomstate.viewport);
7062         GL_BlendFunc(GL_ONE, GL_ZERO);
7063         GL_Color(colorscale, colorscale, colorscale, 1);
7064         // TODO: optimize with multitexture or GLSL
7065         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7066         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7067         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7068         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7069
7070         // we now have a bloom image in the framebuffer
7071         // copy it into the bloom image texture for later processing
7072         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7073         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7074 }
7075
7076 void R_Bloom_CopyHDRTexture(void)
7077 {
7078         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7079         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7080 }
7081
7082 void R_Bloom_MakeTexture(void)
7083 {
7084         int x, range, dir;
7085         float xoffset, yoffset, r, brighten;
7086
7087         r_refdef.stats.bloom++;
7088
7089         R_ResetViewRendering2D();
7090         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7091         R_Mesh_ColorPointer(NULL, 0, 0);
7092
7093         // we have a bloom image in the framebuffer
7094         CHECKGLERROR
7095         R_SetViewport(&r_bloomstate.viewport);
7096
7097         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7098         {
7099                 x *= 2;
7100                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7101                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7102                 GL_Color(r, r, r, 1);
7103                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7104                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7105                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7106                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7107
7108                 // copy the vertically blurred bloom view to a texture
7109                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7110                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7111         }
7112
7113         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7114         brighten = r_bloom_brighten.value;
7115         if (r_hdr.integer)
7116                 brighten *= r_hdr_range.value;
7117         brighten = sqrt(brighten);
7118         if(range >= 1)
7119                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7120         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7121         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7122
7123         for (dir = 0;dir < 2;dir++)
7124         {
7125                 // blend on at multiple vertical offsets to achieve a vertical blur
7126                 // TODO: do offset blends using GLSL
7127                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7128                 GL_BlendFunc(GL_ONE, GL_ZERO);
7129                 for (x = -range;x <= range;x++)
7130                 {
7131                         if (!dir){xoffset = 0;yoffset = x;}
7132                         else {xoffset = x;yoffset = 0;}
7133                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7134                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7135                         // compute a texcoord array with the specified x and y offset
7136                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7137                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7138                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7139                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7140                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7141                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7142                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7143                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7144                         // this r value looks like a 'dot' particle, fading sharply to
7145                         // black at the edges
7146                         // (probably not realistic but looks good enough)
7147                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7148                         //r = brighten/(range*2+1);
7149                         r = brighten / (range * 2 + 1);
7150                         if(range >= 1)
7151                                 r *= (1 - x*x/(float)(range*range));
7152                         GL_Color(r, r, r, 1);
7153                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7154                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7155                         GL_BlendFunc(GL_ONE, GL_ONE);
7156                 }
7157
7158                 // copy the vertically blurred bloom view to a texture
7159                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7160                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7161         }
7162
7163         // apply subtract last
7164         // (just like it would be in a GLSL shader)
7165         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7166         {
7167                 GL_BlendFunc(GL_ONE, GL_ZERO);
7168                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7169                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7170                 GL_Color(1, 1, 1, 1);
7171                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7172                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7173
7174                 GL_BlendFunc(GL_ONE, GL_ONE);
7175                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7176                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7177                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7178                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7179                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7180                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7181                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7182
7183                 // copy the darkened bloom view to a texture
7184                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
7185                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7186         }
7187 }
7188
7189 void R_HDR_RenderBloomTexture(void)
7190 {
7191         int oldwidth, oldheight;
7192         float oldcolorscale;
7193
7194         oldcolorscale = r_refdef.view.colorscale;
7195         oldwidth = r_refdef.view.width;
7196         oldheight = r_refdef.view.height;
7197         r_refdef.view.width = r_bloomstate.bloomwidth;
7198         r_refdef.view.height = r_bloomstate.bloomheight;
7199
7200         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7201         // TODO: add exposure compensation features
7202         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7203
7204         r_refdef.view.showdebug = false;
7205         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7206
7207         R_ResetViewRendering3D();
7208
7209         R_ClearScreen(r_refdef.fogenabled);
7210         if (r_timereport_active)
7211                 R_TimeReport("HDRclear");
7212
7213         R_View_Update();
7214         if (r_timereport_active)
7215                 R_TimeReport("visibility");
7216
7217         // only do secondary renders with HDR if r_hdr is 2 or higher
7218         r_waterstate.numwaterplanes = 0;
7219         if (r_waterstate.enabled && r_hdr.integer >= 2)
7220                 R_RenderWaterPlanes();
7221
7222         r_refdef.view.showdebug = true;
7223         R_RenderScene();
7224         r_waterstate.numwaterplanes = 0;
7225
7226         R_ResetViewRendering2D();
7227
7228         R_Bloom_CopyHDRTexture();
7229         R_Bloom_MakeTexture();
7230
7231         // restore the view settings
7232         r_refdef.view.width = oldwidth;
7233         r_refdef.view.height = oldheight;
7234         r_refdef.view.colorscale = oldcolorscale;
7235
7236         R_ResetViewRendering3D();
7237
7238         R_ClearScreen(r_refdef.fogenabled);
7239         if (r_timereport_active)
7240                 R_TimeReport("viewclear");
7241 }
7242
7243 static void R_BlendView(void)
7244 {
7245         unsigned int permutation;
7246         float uservecs[4][4];
7247
7248         switch (vid.renderpath)
7249         {
7250         case RENDERPATH_GL20:
7251         case RENDERPATH_CGGL:
7252                 permutation =
7253                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7254                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7255                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7256                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7257                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7258
7259                 if (r_bloomstate.texture_screen)
7260                 {
7261                         // make sure the buffer is available
7262                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7263
7264                         R_ResetViewRendering2D();
7265                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7266                         R_Mesh_ColorPointer(NULL, 0, 0);
7267
7268                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7269                         {
7270                                 // declare variables
7271                                 float speed;
7272                                 static float avgspeed;
7273
7274                                 speed = VectorLength(cl.movement_velocity);
7275
7276                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7277                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7278
7279                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7280                                 speed = bound(0, speed, 1);
7281                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7282
7283                                 // calculate values into a standard alpha
7284                                 cl.motionbluralpha = 1 - exp(-
7285                                                 (
7286                                                  (r_motionblur.value * speed / 80)
7287                                                  +
7288                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7289                                                 )
7290                                                 /
7291                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7292                                            );
7293
7294                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7295                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7296                                 // apply the blur
7297                                 if (cl.motionbluralpha > 0)
7298                                 {
7299                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7300                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7301                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7302                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7303                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7304                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7305                                 }
7306                         }
7307
7308                         // copy view into the screen texture
7309                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7310                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7311                 }
7312                 else if (!r_bloomstate.texture_bloom)
7313                 {
7314                         // we may still have to do view tint...
7315                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7316                         {
7317                                 // apply a color tint to the whole view
7318                                 R_ResetViewRendering2D();
7319                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7320                                 R_Mesh_ColorPointer(NULL, 0, 0);
7321                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7322                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7323                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7324                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7325                         }
7326                         break; // no screen processing, no bloom, skip it
7327                 }
7328
7329                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7330                 {
7331                         // render simple bloom effect
7332                         // copy the screen and shrink it and darken it for the bloom process
7333                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7334                         // make the bloom texture
7335                         R_Bloom_MakeTexture();
7336                 }
7337
7338 #if _MSC_VER >= 1400
7339 #define sscanf sscanf_s
7340 #endif
7341                 memset(uservecs, 0, sizeof(uservecs));
7342                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7343                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7344                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7345                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7346
7347                 R_ResetViewRendering2D();
7348                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7349                 R_Mesh_ColorPointer(NULL, 0, 0);
7350                 GL_Color(1, 1, 1, 1);
7351                 GL_BlendFunc(GL_ONE, GL_ZERO);
7352                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7353                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7354
7355                 switch(vid.renderpath)
7356                 {
7357                 case RENDERPATH_GL20:
7358                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7359                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7360                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7361                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7362                         if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7363                         if (r_glsl_permutation->loc_ClientTime         >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime        , cl.time);
7364                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7365                         if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7366                         if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7367                         if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7368                         if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7369                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7370                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7371                         break;
7372                 case RENDERPATH_CGGL:
7373 #ifdef SUPPORTCG
7374                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7375                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7376                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7377                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7378                         if (r_cg_permutation->fp_ViewTintColor     ) cgGLSetParameter4f(     r_cg_permutation->fp_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);CHECKCGERROR
7379                         if (r_cg_permutation->fp_ClientTime        ) cgGLSetParameter1f(     r_cg_permutation->fp_ClientTime        , cl.time);CHECKCGERROR
7380                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7381                         if (r_cg_permutation->fp_UserVec1          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);CHECKCGERROR
7382                         if (r_cg_permutation->fp_UserVec2          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);CHECKCGERROR
7383                         if (r_cg_permutation->fp_UserVec3          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);CHECKCGERROR
7384                         if (r_cg_permutation->fp_UserVec4          ) cgGLSetParameter4f(     r_cg_permutation->fp_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);CHECKCGERROR
7385                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7386                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7387 #endif
7388                         break;
7389                 default:
7390                         break;
7391                 }
7392                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7393                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7394                 break;
7395         case RENDERPATH_GL13:
7396         case RENDERPATH_GL11:
7397                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7398                 {
7399                         // apply a color tint to the whole view
7400                         R_ResetViewRendering2D();
7401                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7402                         R_Mesh_ColorPointer(NULL, 0, 0);
7403                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7404                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7405                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7406                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7407                 }
7408                 break;
7409         }
7410 }
7411
7412 matrix4x4_t r_waterscrollmatrix;
7413
7414 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7415 {
7416         if (r_refdef.fog_density)
7417         {
7418                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7419                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7420                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7421
7422                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7423                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7424                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7425                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7426
7427                 {
7428                         vec3_t fogvec;
7429                         VectorCopy(r_refdef.fogcolor, fogvec);
7430                         //   color.rgb *= ContrastBoost * SceneBrightness;
7431                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7432                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7433                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7434                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7435                 }
7436         }
7437 }
7438
7439 void R_UpdateVariables(void)
7440 {
7441         R_Textures_Frame();
7442
7443         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7444
7445         r_refdef.farclip = r_farclip_base.value;
7446         if (r_refdef.scene.worldmodel)
7447                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7448         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7449
7450         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7451                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7452         r_refdef.polygonfactor = 0;
7453         r_refdef.polygonoffset = 0;
7454         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7455         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7456
7457         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7458         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7459         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7460         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7461         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7462         if (r_showsurfaces.integer)
7463         {
7464                 r_refdef.scene.rtworld = false;
7465                 r_refdef.scene.rtworldshadows = false;
7466                 r_refdef.scene.rtdlight = false;
7467                 r_refdef.scene.rtdlightshadows = false;
7468                 r_refdef.lightmapintensity = 0;
7469         }
7470
7471         if (gamemode == GAME_NEHAHRA)
7472         {
7473                 if (gl_fogenable.integer)
7474                 {
7475                         r_refdef.oldgl_fogenable = true;
7476                         r_refdef.fog_density = gl_fogdensity.value;
7477                         r_refdef.fog_red = gl_fogred.value;
7478                         r_refdef.fog_green = gl_foggreen.value;
7479                         r_refdef.fog_blue = gl_fogblue.value;
7480                         r_refdef.fog_alpha = 1;
7481                         r_refdef.fog_start = 0;
7482                         r_refdef.fog_end = gl_skyclip.value;
7483                         r_refdef.fog_height = 1<<30;
7484                         r_refdef.fog_fadedepth = 128;
7485                 }
7486                 else if (r_refdef.oldgl_fogenable)
7487                 {
7488                         r_refdef.oldgl_fogenable = false;
7489                         r_refdef.fog_density = 0;
7490                         r_refdef.fog_red = 0;
7491                         r_refdef.fog_green = 0;
7492                         r_refdef.fog_blue = 0;
7493                         r_refdef.fog_alpha = 0;
7494                         r_refdef.fog_start = 0;
7495                         r_refdef.fog_end = 0;
7496                         r_refdef.fog_height = 1<<30;
7497                         r_refdef.fog_fadedepth = 128;
7498                 }
7499         }
7500
7501         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7502         r_refdef.fog_start = max(0, r_refdef.fog_start);
7503         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7504
7505         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
7506
7507         if (r_refdef.fog_density && r_drawfog.integer)
7508         {
7509                 r_refdef.fogenabled = true;
7510                 // this is the point where the fog reaches 0.9986 alpha, which we
7511                 // consider a good enough cutoff point for the texture
7512                 // (0.9986 * 256 == 255.6)
7513                 if (r_fog_exp2.integer)
7514                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7515                 else
7516                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7517                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7518                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7519                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7520                 // fog color was already set
7521                 // update the fog texture
7522                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
7523                         R_BuildFogTexture();
7524         }
7525         else
7526                 r_refdef.fogenabled = false;
7527
7528         switch(vid.renderpath)
7529         {
7530         case RENDERPATH_GL20:
7531         case RENDERPATH_CGGL:
7532                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7533                 {
7534                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7535                         {
7536                                 // build GLSL gamma texture
7537 #define RAMPWIDTH 256
7538                                 unsigned short ramp[RAMPWIDTH * 3];
7539                                 unsigned char rampbgr[RAMPWIDTH][4];
7540                                 int i;
7541
7542                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7543
7544                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7545                                 for(i = 0; i < RAMPWIDTH; ++i)
7546                                 {
7547                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7548                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7549                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7550                                         rampbgr[i][3] = 0;
7551                                 }
7552                                 if (r_texture_gammaramps)
7553                                 {
7554                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
7555                                 }
7556                                 else
7557                                 {
7558                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, NULL);
7559                                 }
7560                         }
7561                 }
7562                 else
7563                 {
7564                         // remove GLSL gamma texture
7565                 }
7566                 break;
7567         case RENDERPATH_GL13:
7568         case RENDERPATH_GL11:
7569                 break;
7570         }
7571 }
7572
7573 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7574 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7575 /*
7576 ================
7577 R_SelectScene
7578 ================
7579 */
7580 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7581         if( scenetype != r_currentscenetype ) {
7582                 // store the old scenetype
7583                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7584                 r_currentscenetype = scenetype;
7585                 // move in the new scene
7586                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7587         }
7588 }
7589
7590 /*
7591 ================
7592 R_GetScenePointer
7593 ================
7594 */
7595 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7596 {
7597         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7598         if( scenetype == r_currentscenetype ) {
7599                 return &r_refdef.scene;
7600         } else {
7601                 return &r_scenes_store[ scenetype ];
7602         }
7603 }
7604
7605 /*
7606 ================
7607 R_RenderView
7608 ================
7609 */
7610 void R_RenderView(void)
7611 {
7612         if (r_timereport_active)
7613                 R_TimeReport("start");
7614         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7615
7616         if (!r_drawentities.integer)
7617                 r_refdef.scene.numentities = 0;
7618
7619         R_AnimCache_ClearCache();
7620         R_FrameData_NewFrame();
7621
7622         if (r_refdef.view.isoverlay)
7623         {
7624                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7625                 GL_Clear( GL_DEPTH_BUFFER_BIT );
7626                 R_TimeReport("depthclear");
7627
7628                 r_refdef.view.showdebug = false;
7629
7630                 r_waterstate.enabled = false;
7631                 r_waterstate.numwaterplanes = 0;
7632
7633                 R_RenderScene();
7634
7635                 CHECKGLERROR
7636                 return;
7637         }
7638
7639         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
7640                 return; //Host_Error ("R_RenderView: NULL worldmodel");
7641
7642         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
7643
7644         // break apart the view matrix into vectors for various purposes
7645         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7646         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7647         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7648         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7649         // make an inverted copy of the view matrix for tracking sprites
7650         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7651
7652         R_Shadow_UpdateWorldLightSelection();
7653
7654         R_Bloom_StartFrame();
7655         R_Water_StartFrame();
7656
7657         CHECKGLERROR
7658         if (r_timereport_active)
7659                 R_TimeReport("viewsetup");
7660
7661         R_ResetViewRendering3D();
7662
7663         if (r_refdef.view.clear || r_refdef.fogenabled)
7664         {
7665                 R_ClearScreen(r_refdef.fogenabled);
7666                 if (r_timereport_active)
7667                         R_TimeReport("viewclear");
7668         }
7669         r_refdef.view.clear = true;
7670
7671         // this produces a bloom texture to be used in R_BlendView() later
7672         if (r_hdr.integer && r_bloomstate.bloomwidth)
7673                 R_HDR_RenderBloomTexture();
7674
7675         r_refdef.view.showdebug = true;
7676
7677         R_View_Update();
7678         if (r_timereport_active)
7679                 R_TimeReport("visibility");
7680
7681         r_waterstate.numwaterplanes = 0;
7682         if (r_waterstate.enabled)
7683                 R_RenderWaterPlanes();
7684
7685         R_RenderScene();
7686         r_waterstate.numwaterplanes = 0;
7687
7688         R_BlendView();
7689         if (r_timereport_active)
7690                 R_TimeReport("blendview");
7691
7692         GL_Scissor(0, 0, vid.width, vid.height);
7693         GL_ScissorTest(false);
7694         CHECKGLERROR
7695 }
7696
7697 void R_RenderWaterPlanes(void)
7698 {
7699         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7700         {
7701                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7702                 if (r_timereport_active)
7703                         R_TimeReport("waterworld");
7704         }
7705
7706         // don't let sound skip if going slow
7707         if (r_refdef.scene.extraupdate)
7708                 S_ExtraUpdate ();
7709
7710         R_DrawModelsAddWaterPlanes();
7711         if (r_timereport_active)
7712                 R_TimeReport("watermodels");
7713
7714         if (r_waterstate.numwaterplanes)
7715         {
7716                 R_Water_ProcessPlanes();
7717                 if (r_timereport_active)
7718                         R_TimeReport("waterscenes");
7719         }
7720 }
7721
7722 extern void R_DrawLightningBeams (void);
7723 extern void VM_CL_AddPolygonsToMeshQueue (void);
7724 extern void R_DrawPortals (void);
7725 extern cvar_t cl_locs_show;
7726 static void R_DrawLocs(void);
7727 static void R_DrawEntityBBoxes(void);
7728 static void R_DrawModelDecals(void);
7729 extern cvar_t cl_decals_newsystem;
7730 extern qboolean r_shadow_usingdeferredprepass;
7731 void R_RenderScene(void)
7732 {
7733         r_refdef.stats.renders++;
7734         r_textureframe++; // used only by R_GetCurrentTexture
7735
7736         R_UpdateFogColor();
7737
7738         // don't let sound skip if going slow
7739         if (r_refdef.scene.extraupdate)
7740                 S_ExtraUpdate ();
7741
7742         R_MeshQueue_BeginScene();
7743
7744         R_SkyStartFrame();
7745
7746         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
7747
7748         if (cl.csqc_vidvars.drawworld)
7749         {
7750                 // don't let sound skip if going slow
7751                 if (r_refdef.scene.extraupdate)
7752                         S_ExtraUpdate ();
7753
7754                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7755                 {
7756                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7757                         if (r_timereport_active)
7758                                 R_TimeReport("worldsky");
7759                 }
7760
7761                 if (R_DrawBrushModelsSky() && r_timereport_active)
7762                         R_TimeReport("bmodelsky");
7763
7764                 if (skyrendermasked && skyrenderlater)
7765                 {
7766                         // we have to force off the water clipping plane while rendering sky
7767                         R_SetupView(false);
7768                         R_Sky();
7769                         R_SetupView(true);
7770                         if (r_timereport_active)
7771                                 R_TimeReport("sky");
7772                 }
7773         }
7774
7775         R_AnimCache_CacheVisibleEntities();
7776         if (r_timereport_active)
7777                 R_TimeReport("animation");
7778
7779         R_Shadow_PrepareLights();
7780         if (r_timereport_active)
7781                 R_TimeReport("preparelights");
7782
7783         if (r_shadow_usingdeferredprepass)
7784                 R_Shadow_DrawPrepass();
7785
7786         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7787         {
7788                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7789                 if (r_timereport_active)
7790                         R_TimeReport("worlddepth");
7791         }
7792         if (r_depthfirst.integer >= 2)
7793         {
7794                 R_DrawModelsDepth();
7795                 if (r_timereport_active)
7796                         R_TimeReport("modeldepth");
7797         }
7798
7799         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7800         {
7801                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7802                 if (r_timereport_active)
7803                         R_TimeReport("world");
7804         }
7805
7806         // don't let sound skip if going slow
7807         if (r_refdef.scene.extraupdate)
7808                 S_ExtraUpdate ();
7809
7810         R_DrawModels();
7811         if (r_timereport_active)
7812                 R_TimeReport("models");
7813
7814         // don't let sound skip if going slow
7815         if (r_refdef.scene.extraupdate)
7816                 S_ExtraUpdate ();
7817
7818         if (r_shadows.integer > 0 && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7819         {
7820                 R_DrawModelShadows();
7821                 R_ResetViewRendering3D();
7822                 // don't let sound skip if going slow
7823                 if (r_refdef.scene.extraupdate)
7824                         S_ExtraUpdate ();
7825         }
7826
7827         if (!r_shadow_usingdeferredprepass)
7828         {
7829                 R_Shadow_DrawLights();
7830                 if (r_timereport_active)
7831                         R_TimeReport("rtlights");
7832         }
7833
7834         // don't let sound skip if going slow
7835         if (r_refdef.scene.extraupdate)
7836                 S_ExtraUpdate ();
7837
7838         if (r_shadows.integer > 0 && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7839         {
7840                 R_DrawModelShadows();
7841                 R_ResetViewRendering3D();
7842                 // don't let sound skip if going slow
7843                 if (r_refdef.scene.extraupdate)
7844                         S_ExtraUpdate ();
7845         }
7846
7847         if (cl.csqc_vidvars.drawworld)
7848         {
7849                 if (cl_decals_newsystem.integer)
7850                 {
7851                         R_DrawModelDecals();
7852                         if (r_timereport_active)
7853                                 R_TimeReport("modeldecals");
7854                 }
7855                 else
7856                 {
7857                         R_DrawDecals();
7858                         if (r_timereport_active)
7859                                 R_TimeReport("decals");
7860                 }
7861
7862                 R_DrawParticles();
7863                 if (r_timereport_active)
7864                         R_TimeReport("particles");
7865
7866                 R_DrawExplosions();
7867                 if (r_timereport_active)
7868                         R_TimeReport("explosions");
7869
7870                 R_DrawLightningBeams();
7871                 if (r_timereport_active)
7872                         R_TimeReport("lightning");
7873         }
7874
7875         VM_CL_AddPolygonsToMeshQueue();
7876
7877         if (r_refdef.view.showdebug)
7878         {
7879                 if (cl_locs_show.integer)
7880                 {
7881                         R_DrawLocs();
7882                         if (r_timereport_active)
7883                                 R_TimeReport("showlocs");
7884                 }
7885
7886                 if (r_drawportals.integer)
7887                 {
7888                         R_DrawPortals();
7889                         if (r_timereport_active)
7890                                 R_TimeReport("portals");
7891                 }
7892
7893                 if (r_showbboxes.value > 0)
7894                 {
7895                         R_DrawEntityBBoxes();
7896                         if (r_timereport_active)
7897                                 R_TimeReport("bboxes");
7898                 }
7899         }
7900
7901         R_MeshQueue_RenderTransparent();
7902         if (r_timereport_active)
7903                 R_TimeReport("drawtrans");
7904
7905         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0))
7906         {
7907                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7908                 if (r_timereport_active)
7909                         R_TimeReport("worlddebug");
7910                 R_DrawModelsDebug();
7911                 if (r_timereport_active)
7912                         R_TimeReport("modeldebug");
7913         }
7914
7915         if (cl.csqc_vidvars.drawworld)
7916         {
7917                 R_Shadow_DrawCoronas();
7918                 if (r_timereport_active)
7919                         R_TimeReport("coronas");
7920         }
7921
7922         // don't let sound skip if going slow
7923         if (r_refdef.scene.extraupdate)
7924                 S_ExtraUpdate ();
7925
7926         R_ResetViewRendering2D();
7927 }
7928
7929 static const unsigned short bboxelements[36] =
7930 {
7931         5, 1, 3, 5, 3, 7,
7932         6, 2, 0, 6, 0, 4,
7933         7, 3, 2, 7, 2, 6,
7934         4, 0, 1, 4, 1, 5,
7935         4, 5, 7, 4, 7, 6,
7936         1, 0, 2, 1, 2, 3,
7937 };
7938
7939 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7940 {
7941         int i;
7942         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7943
7944         RSurf_ActiveWorldEntity();
7945
7946         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7947         GL_DepthMask(false);
7948         GL_DepthRange(0, 1);
7949         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7950         R_Mesh_ResetTextureState();
7951
7952         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7953         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7954         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7955         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7956         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7957         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7958         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7959         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7960         R_FillColors(color4f, 8, cr, cg, cb, ca);
7961         if (r_refdef.fogenabled)
7962         {
7963                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7964                 {
7965                         f1 = RSurf_FogVertex(v);
7966                         f2 = 1 - f1;
7967                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7968                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7969                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7970                 }
7971         }
7972         R_Mesh_VertexPointer(vertex3f, 0, 0);
7973         R_Mesh_ColorPointer(color4f, 0, 0);
7974         R_Mesh_ResetTextureState();
7975         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7976         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
7977 }
7978
7979 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7980 {
7981         int i;
7982         float color[4];
7983         prvm_edict_t *edict;
7984         prvm_prog_t *prog_save = prog;
7985
7986         // this function draws bounding boxes of server entities
7987         if (!sv.active)
7988                 return;
7989
7990         GL_CullFace(GL_NONE);
7991         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7992
7993         prog = 0;
7994         SV_VM_Begin();
7995         for (i = 0;i < numsurfaces;i++)
7996         {
7997                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7998                 switch ((int)edict->fields.server->solid)
7999                 {
8000                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8001                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8002                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8003                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8004                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8005                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8006                 }
8007                 color[3] *= r_showbboxes.value;
8008                 color[3] = bound(0, color[3], 1);
8009                 GL_DepthTest(!r_showdisabledepthtest.integer);
8010                 GL_CullFace(r_refdef.view.cullface_front);
8011                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8012         }
8013         SV_VM_End();
8014         prog = prog_save;
8015 }
8016
8017 static void R_DrawEntityBBoxes(void)
8018 {
8019         int i;
8020         prvm_edict_t *edict;
8021         vec3_t center;
8022         prvm_prog_t *prog_save = prog;
8023
8024         // this function draws bounding boxes of server entities
8025         if (!sv.active)
8026                 return;
8027
8028         prog = 0;
8029         SV_VM_Begin();
8030         for (i = 0;i < prog->num_edicts;i++)
8031         {
8032                 edict = PRVM_EDICT_NUM(i);
8033                 if (edict->priv.server->free)
8034                         continue;
8035                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8036                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8037                         continue;
8038                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8039                         continue;
8040                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8041                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8042         }
8043         SV_VM_End();
8044         prog = prog_save;
8045 }
8046
8047 static const int nomodelelement3i[24] =
8048 {
8049         5, 2, 0,
8050         5, 1, 2,
8051         5, 0, 3,
8052         5, 3, 1,
8053         0, 2, 4,
8054         2, 1, 4,
8055         3, 0, 4,
8056         1, 3, 4
8057 };
8058
8059 static const unsigned short nomodelelement3s[24] =
8060 {
8061         5, 2, 0,
8062         5, 1, 2,
8063         5, 0, 3,
8064         5, 3, 1,
8065         0, 2, 4,
8066         2, 1, 4,
8067         3, 0, 4,
8068         1, 3, 4
8069 };
8070
8071 static const float nomodelvertex3f[6*3] =
8072 {
8073         -16,   0,   0,
8074          16,   0,   0,
8075           0, -16,   0,
8076           0,  16,   0,
8077           0,   0, -16,
8078           0,   0,  16
8079 };
8080
8081 static const float nomodelcolor4f[6*4] =
8082 {
8083         0.0f, 0.0f, 0.5f, 1.0f,
8084         0.0f, 0.0f, 0.5f, 1.0f,
8085         0.0f, 0.5f, 0.0f, 1.0f,
8086         0.0f, 0.5f, 0.0f, 1.0f,
8087         0.5f, 0.0f, 0.0f, 1.0f,
8088         0.5f, 0.0f, 0.0f, 1.0f
8089 };
8090
8091 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8092 {
8093         int i;
8094         float f1, f2, *c;
8095         float color4f[6*4];
8096
8097         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
8098
8099         // this is only called once per entity so numsurfaces is always 1, and
8100         // surfacelist is always {0}, so this code does not handle batches
8101
8102         if (rsurface.ent_flags & RENDER_ADDITIVE)
8103         {
8104                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8105                 GL_DepthMask(false);
8106         }
8107         else if (rsurface.colormod[3] < 1)
8108         {
8109                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8110                 GL_DepthMask(false);
8111         }
8112         else
8113         {
8114                 GL_BlendFunc(GL_ONE, GL_ZERO);
8115                 GL_DepthMask(true);
8116         }
8117         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8118         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8119         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8120         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8121         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8122         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8123         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8124         R_Mesh_ColorPointer(color4f, 0, 0);
8125         for (i = 0, c = color4f;i < 6;i++, c += 4)
8126         {
8127                 c[0] *= rsurface.colormod[0];
8128                 c[1] *= rsurface.colormod[1];
8129                 c[2] *= rsurface.colormod[2];
8130                 c[3] *= rsurface.colormod[3];
8131         }
8132         if (r_refdef.fogenabled)
8133         {
8134                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8135                 {
8136                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8137                         f2 = 1 - f1;
8138                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8139                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8140                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8141                 }
8142         }
8143         R_Mesh_ResetTextureState();
8144         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8145 }
8146
8147 void R_DrawNoModel(entity_render_t *ent)
8148 {
8149         vec3_t org;
8150         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8151         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8152                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8153         else
8154                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8155 }
8156
8157 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8158 {
8159         vec3_t right1, right2, diff, normal;
8160
8161         VectorSubtract (org2, org1, normal);
8162
8163         // calculate 'right' vector for start
8164         VectorSubtract (r_refdef.view.origin, org1, diff);
8165         CrossProduct (normal, diff, right1);
8166         VectorNormalize (right1);
8167
8168         // calculate 'right' vector for end
8169         VectorSubtract (r_refdef.view.origin, org2, diff);
8170         CrossProduct (normal, diff, right2);
8171         VectorNormalize (right2);
8172
8173         vert[ 0] = org1[0] + width * right1[0];
8174         vert[ 1] = org1[1] + width * right1[1];
8175         vert[ 2] = org1[2] + width * right1[2];
8176         vert[ 3] = org1[0] - width * right1[0];
8177         vert[ 4] = org1[1] - width * right1[1];
8178         vert[ 5] = org1[2] - width * right1[2];
8179         vert[ 6] = org2[0] - width * right2[0];
8180         vert[ 7] = org2[1] - width * right2[1];
8181         vert[ 8] = org2[2] - width * right2[2];
8182         vert[ 9] = org2[0] + width * right2[0];
8183         vert[10] = org2[1] + width * right2[1];
8184         vert[11] = org2[2] + width * right2[2];
8185 }
8186
8187 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
8188 {
8189         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8190         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8191         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8192         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8193         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8194         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8195         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8196         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8197         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8198         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8199         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8200         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8201 }
8202
8203 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8204 {
8205         int i;
8206         float *vertex3f;
8207         float v[3];
8208         VectorSet(v, x, y, z);
8209         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8210                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8211                         break;
8212         if (i == mesh->numvertices)
8213         {
8214                 if (mesh->numvertices < mesh->maxvertices)
8215                 {
8216                         VectorCopy(v, vertex3f);
8217                         mesh->numvertices++;
8218                 }
8219                 return mesh->numvertices;
8220         }
8221         else
8222                 return i;
8223 }
8224
8225 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8226 {
8227         int i;
8228         int *e, element[3];
8229         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8230         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8231         e = mesh->element3i + mesh->numtriangles * 3;
8232         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8233         {
8234                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8235                 if (mesh->numtriangles < mesh->maxtriangles)
8236                 {
8237                         *e++ = element[0];
8238                         *e++ = element[1];
8239                         *e++ = element[2];
8240                         mesh->numtriangles++;
8241                 }
8242                 element[1] = element[2];
8243         }
8244 }
8245
8246 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8247 {
8248         int i;
8249         int *e, element[3];
8250         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8251         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8252         e = mesh->element3i + mesh->numtriangles * 3;
8253         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8254         {
8255                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8256                 if (mesh->numtriangles < mesh->maxtriangles)
8257                 {
8258                         *e++ = element[0];
8259                         *e++ = element[1];
8260                         *e++ = element[2];
8261                         mesh->numtriangles++;
8262                 }
8263                 element[1] = element[2];
8264         }
8265 }
8266
8267 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8268 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8269 {
8270         int planenum, planenum2;
8271         int w;
8272         int tempnumpoints;
8273         mplane_t *plane, *plane2;
8274         double maxdist;
8275         double temppoints[2][256*3];
8276         // figure out how large a bounding box we need to properly compute this brush
8277         maxdist = 0;
8278         for (w = 0;w < numplanes;w++)
8279                 maxdist = max(maxdist, fabs(planes[w].dist));
8280         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8281         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8282         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8283         {
8284                 w = 0;
8285                 tempnumpoints = 4;
8286                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8287                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8288                 {
8289                         if (planenum2 == planenum)
8290                                 continue;
8291                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
8292                         w = !w;
8293                 }
8294                 if (tempnumpoints < 3)
8295                         continue;
8296                 // generate elements forming a triangle fan for this polygon
8297                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8298         }
8299 }
8300
8301 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
8302 {
8303         texturelayer_t *layer;
8304         layer = t->currentlayers + t->currentnumlayers++;
8305         layer->type = type;
8306         layer->depthmask = depthmask;
8307         layer->blendfunc1 = blendfunc1;
8308         layer->blendfunc2 = blendfunc2;
8309         layer->texture = texture;
8310         layer->texmatrix = *matrix;
8311         layer->color[0] = r;
8312         layer->color[1] = g;
8313         layer->color[2] = b;
8314         layer->color[3] = a;
8315 }
8316
8317 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8318 {
8319         double index, f;
8320         index = parms[2] + r_refdef.scene.time * parms[3];
8321         index -= floor(index);
8322         switch (func)
8323         {
8324         default:
8325         case Q3WAVEFUNC_NONE:
8326         case Q3WAVEFUNC_NOISE:
8327         case Q3WAVEFUNC_COUNT:
8328                 f = 0;
8329                 break;
8330         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8331         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8332         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8333         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8334         case Q3WAVEFUNC_TRIANGLE:
8335                 index *= 4;
8336                 f = index - floor(index);
8337                 if (index < 1)
8338                         f = f;
8339                 else if (index < 2)
8340                         f = 1 - f;
8341                 else if (index < 3)
8342                         f = -f;
8343                 else
8344                         f = -(1 - f);
8345                 break;
8346         }
8347         return (float)(parms[0] + parms[1] * f);
8348 }
8349
8350 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8351 {
8352         int w, h, idx;
8353         float f;
8354         float tcmat[12];
8355         matrix4x4_t matrix, temp;
8356         switch(tcmod->tcmod)
8357         {
8358                 case Q3TCMOD_COUNT:
8359                 case Q3TCMOD_NONE:
8360                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8361                                 matrix = r_waterscrollmatrix;
8362                         else
8363                                 matrix = identitymatrix;
8364                         break;
8365                 case Q3TCMOD_ENTITYTRANSLATE:
8366                         // this is used in Q3 to allow the gamecode to control texcoord
8367                         // scrolling on the entity, which is not supported in darkplaces yet.
8368                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8369                         break;
8370                 case Q3TCMOD_ROTATE:
8371                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8372                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8373                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8374                         break;
8375                 case Q3TCMOD_SCALE:
8376                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8377                         break;
8378                 case Q3TCMOD_SCROLL:
8379                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8380                         break;
8381                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8382                         w = (int) tcmod->parms[0];
8383                         h = (int) tcmod->parms[1];
8384                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8385                         f = f - floor(f);
8386                         idx = (int) floor(f * w * h);
8387                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8388                         break;
8389                 case Q3TCMOD_STRETCH:
8390                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8391                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8392                         break;
8393                 case Q3TCMOD_TRANSFORM:
8394                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8395                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8396                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8397                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8398                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8399                         break;
8400                 case Q3TCMOD_TURBULENT:
8401                         // this is handled in the RSurf_PrepareVertices function
8402                         matrix = identitymatrix;
8403                         break;
8404         }
8405         temp = *texmatrix;
8406         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8407 }
8408
8409 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8410 {
8411         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8412         char name[MAX_QPATH];
8413         skinframe_t *skinframe;
8414         unsigned char pixels[296*194];
8415         strlcpy(cache->name, skinname, sizeof(cache->name));
8416         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8417         if (developer_loading.integer)
8418                 Con_Printf("loading %s\n", name);
8419         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8420         if (!skinframe || !skinframe->base)
8421         {
8422                 unsigned char *f;
8423                 fs_offset_t filesize;
8424                 skinframe = NULL;
8425                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8426                 if (f)
8427                 {
8428                         if (LoadPCX_QWSkin(f, filesize, pixels, 296, 194))
8429                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8430                         Mem_Free(f);
8431                 }
8432         }
8433         cache->skinframe = skinframe;
8434 }
8435
8436 texture_t *R_GetCurrentTexture(texture_t *t)
8437 {
8438         int i;
8439         const entity_render_t *ent = rsurface.entity;
8440         dp_model_t *model = ent->model;
8441         q3shaderinfo_layer_tcmod_t *tcmod;
8442
8443         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8444                 return t->currentframe;
8445         t->update_lastrenderframe = r_textureframe;
8446         t->update_lastrenderentity = (void *)ent;
8447
8448         // switch to an alternate material if this is a q1bsp animated material
8449         {
8450                 texture_t *texture = t;
8451                 int s = rsurface.ent_skinnum;
8452                 if ((unsigned int)s >= (unsigned int)model->numskins)
8453                         s = 0;
8454                 if (model->skinscenes)
8455                 {
8456                         if (model->skinscenes[s].framecount > 1)
8457                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8458                         else
8459                                 s = model->skinscenes[s].firstframe;
8460                 }
8461                 if (s > 0)
8462                         t = t + s * model->num_surfaces;
8463                 if (t->animated)
8464                 {
8465                         // use an alternate animation if the entity's frame is not 0,
8466                         // and only if the texture has an alternate animation
8467                         if (rsurface.ent_alttextures && t->anim_total[1])
8468                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8469                         else
8470                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8471                 }
8472                 texture->currentframe = t;
8473         }
8474
8475         // update currentskinframe to be a qw skin or animation frame
8476         if (rsurface.ent_qwskin >= 0)
8477         {
8478                 i = rsurface.ent_qwskin;
8479                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8480                 {
8481                         r_qwskincache_size = cl.maxclients;
8482                         if (r_qwskincache)
8483                                 Mem_Free(r_qwskincache);
8484                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8485                 }
8486                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8487                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8488                 t->currentskinframe = r_qwskincache[i].skinframe;
8489                 if (t->currentskinframe == NULL)
8490                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8491         }
8492         else if (t->numskinframes >= 2)
8493                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
8494         if (t->backgroundnumskinframes >= 2)
8495                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
8496
8497         t->currentmaterialflags = t->basematerialflags;
8498         t->currentalpha = rsurface.colormod[3];
8499         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
8500                 t->currentalpha *= r_wateralpha.value;
8501         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
8502                 t->currentalpha *= t->r_water_wateralpha;
8503         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
8504                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
8505         if (!(rsurface.ent_flags & RENDER_LIGHT))
8506                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8507         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8508         {
8509                 // pick a model lighting mode
8510                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8511                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8512                 else
8513                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8514         }
8515         if (rsurface.ent_flags & RENDER_ADDITIVE)
8516                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8517         else if (t->currentalpha < 1)
8518                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8519         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8520                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8521         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8522                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8523         if (t->backgroundnumskinframes)
8524                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8525         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8526         {
8527                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
8528                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8529         }
8530         else
8531                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
8532         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8533                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8534
8535         // there is no tcmod
8536         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8537         {
8538                 t->currenttexmatrix = r_waterscrollmatrix;
8539                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8540         }
8541         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8542         {
8543                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8544                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8545         }
8546
8547         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8548                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8549         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8550                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8551
8552         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8553         if (t->currentskinframe->qpixels)
8554                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8555         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8556         if (!t->basetexture)
8557                 t->basetexture = r_texture_notexture;
8558         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8559         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8560         t->nmaptexture = t->currentskinframe->nmap;
8561         if (!t->nmaptexture)
8562                 t->nmaptexture = r_texture_blanknormalmap;
8563         t->glosstexture = r_texture_black;
8564         t->glowtexture = t->currentskinframe->glow;
8565         t->fogtexture = t->currentskinframe->fog;
8566         if (t->backgroundnumskinframes)
8567         {
8568                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8569                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8570                 t->backgroundglosstexture = r_texture_black;
8571                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8572                 if (!t->backgroundnmaptexture)
8573                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8574         }
8575         else
8576         {
8577                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
8578                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8579                 t->backgroundglosstexture = r_texture_black;
8580                 t->backgroundglowtexture = NULL;
8581         }
8582         t->specularpower = r_shadow_glossexponent.value;
8583         // TODO: store reference values for these in the texture?
8584         t->specularscale = 0;
8585         if (r_shadow_gloss.integer > 0)
8586         {
8587                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8588                 {
8589                         if (r_shadow_glossintensity.value > 0)
8590                         {
8591                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8592                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8593                                 t->specularscale = r_shadow_glossintensity.value;
8594                         }
8595                 }
8596                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8597                 {
8598                         t->glosstexture = r_texture_white;
8599                         t->backgroundglosstexture = r_texture_white;
8600                         t->specularscale = r_shadow_gloss2intensity.value;
8601                         t->specularpower = r_shadow_gloss2exponent.value;
8602                 }
8603         }
8604         t->specularscale *= t->specularscalemod;
8605         t->specularpower *= t->specularpowermod;
8606
8607         // lightmaps mode looks bad with dlights using actual texturing, so turn
8608         // off the colormap and glossmap, but leave the normalmap on as it still
8609         // accurately represents the shading involved
8610         if (gl_lightmaps.integer)
8611         {
8612                 t->basetexture = r_texture_grey128;
8613                 t->pantstexture = r_texture_black;
8614                 t->shirttexture = r_texture_black;
8615                 t->nmaptexture = r_texture_blanknormalmap;
8616                 t->glosstexture = r_texture_black;
8617                 t->glowtexture = NULL;
8618                 t->fogtexture = NULL;
8619                 t->backgroundbasetexture = NULL;
8620                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8621                 t->backgroundglosstexture = r_texture_black;
8622                 t->backgroundglowtexture = NULL;
8623                 t->specularscale = 0;
8624                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8625         }
8626
8627         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8628         VectorClear(t->dlightcolor);
8629         t->currentnumlayers = 0;
8630         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8631         {
8632                 int blendfunc1, blendfunc2;
8633                 qboolean depthmask;
8634                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8635                 {
8636                         blendfunc1 = GL_SRC_ALPHA;
8637                         blendfunc2 = GL_ONE;
8638                 }
8639                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8640                 {
8641                         blendfunc1 = GL_SRC_ALPHA;
8642                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8643                 }
8644                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8645                 {
8646                         blendfunc1 = t->customblendfunc[0];
8647                         blendfunc2 = t->customblendfunc[1];
8648                 }
8649                 else
8650                 {
8651                         blendfunc1 = GL_ONE;
8652                         blendfunc2 = GL_ZERO;
8653                 }
8654                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8655                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8656                 {
8657                         // fullbright is not affected by r_refdef.lightmapintensity
8658                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8659                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8660                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8661                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8662                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8663                 }
8664                 else
8665                 {
8666                         vec3_t ambientcolor;
8667                         float colorscale;
8668                         // set the color tint used for lights affecting this surface
8669                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8670                         colorscale = 2;
8671                         // q3bsp has no lightmap updates, so the lightstylevalue that
8672                         // would normally be baked into the lightmap must be
8673                         // applied to the color
8674                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8675                         if (model->type == mod_brushq3)
8676                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8677                         colorscale *= r_refdef.lightmapintensity;
8678                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8679                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8680                         // basic lit geometry
8681                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8682                         // add pants/shirt if needed
8683                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8684                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8685                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8686                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8687                         // now add ambient passes if needed
8688                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8689                         {
8690                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8691                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8692                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8693                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8694                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8695                         }
8696                 }
8697                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8698                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8699                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8700                 {
8701                         // if this is opaque use alpha blend which will darken the earlier
8702                         // passes cheaply.
8703                         //
8704                         // if this is an alpha blended material, all the earlier passes
8705                         // were darkened by fog already, so we only need to add the fog
8706                         // color ontop through the fog mask texture
8707                         //
8708                         // if this is an additive blended material, all the earlier passes
8709                         // were darkened by fog already, and we should not add fog color
8710                         // (because the background was not darkened, there is no fog color
8711                         // that was lost behind it).
8712                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8713                 }
8714         }
8715
8716         return t->currentframe;
8717 }
8718
8719 rsurfacestate_t rsurface;
8720
8721 void R_Mesh_ResizeArrays(int newvertices)
8722 {
8723         float *base;
8724         if (rsurface.array_size >= newvertices)
8725                 return;
8726         if (rsurface.array_modelvertex3f)
8727                 Mem_Free(rsurface.array_modelvertex3f);
8728         rsurface.array_size = (newvertices + 1023) & ~1023;
8729         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
8730         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
8731         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
8732         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
8733         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
8734         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
8735         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
8736         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
8737         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
8738         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
8739         rsurface.array_color4f           = base + rsurface.array_size * 27;
8740         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
8741 }
8742
8743 void RSurf_ActiveWorldEntity(void)
8744 {
8745         dp_model_t *model = r_refdef.scene.worldmodel;
8746         //if (rsurface.entity == r_refdef.scene.worldentity)
8747         //      return;
8748         rsurface.entity = r_refdef.scene.worldentity;
8749         rsurface.skeleton = NULL;
8750         rsurface.ent_skinnum = 0;
8751         rsurface.ent_qwskin = -1;
8752         rsurface.ent_shadertime = 0;
8753         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8754         if (rsurface.array_size < model->surfmesh.num_vertices)
8755                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8756         rsurface.matrix = identitymatrix;
8757         rsurface.inversematrix = identitymatrix;
8758         rsurface.matrixscale = 1;
8759         rsurface.inversematrixscale = 1;
8760         R_EntityMatrix(&identitymatrix);
8761         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8762         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8763         rsurface.fograngerecip = r_refdef.fograngerecip;
8764         rsurface.fogheightfade = r_refdef.fogheightfade;
8765         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8766         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8767         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8768         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8769         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8770         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8771         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8772         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8773         rsurface.colormod[3] = 1;
8774         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8775         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8776         rsurface.frameblend[0].lerp = 1;
8777         rsurface.ent_alttextures = false;
8778         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8779         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8780         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8781         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8782         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8783         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8784         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8785         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8786         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8787         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8788         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8789         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8790         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8791         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8792         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8793         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8794         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8795         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8796         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8797         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8798         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8799         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8800         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8801         rsurface.modelelement3i = model->surfmesh.data_element3i;
8802         rsurface.modelelement3s = model->surfmesh.data_element3s;
8803         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8804         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8805         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8806         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8807         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8808         rsurface.modelsurfaces = model->data_surfaces;
8809         rsurface.generatedvertex = false;
8810         rsurface.vertex3f  = rsurface.modelvertex3f;
8811         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8812         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8813         rsurface.svector3f = rsurface.modelsvector3f;
8814         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8815         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8816         rsurface.tvector3f = rsurface.modeltvector3f;
8817         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8818         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8819         rsurface.normal3f  = rsurface.modelnormal3f;
8820         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8821         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8822         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8823 }
8824
8825 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8826 {
8827         dp_model_t *model = ent->model;
8828         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8829         //      return;
8830         rsurface.entity = (entity_render_t *)ent;
8831         rsurface.skeleton = ent->skeleton;
8832         rsurface.ent_skinnum = ent->skinnum;
8833         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8834         rsurface.ent_shadertime = ent->shadertime;
8835         rsurface.ent_flags = ent->flags;
8836         if (rsurface.array_size < model->surfmesh.num_vertices)
8837                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
8838         rsurface.matrix = ent->matrix;
8839         rsurface.inversematrix = ent->inversematrix;
8840         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8841         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8842         R_EntityMatrix(&rsurface.matrix);
8843         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8844         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8845         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8846         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8847         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8848         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8849         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8850         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8851         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8852         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8853         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8854         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8855         rsurface.colormod[3] = ent->alpha;
8856         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8857         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8858         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8859         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8860         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8861         if (ent->model->brush.submodel && !prepass)
8862         {
8863                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8864                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8865         }
8866         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
8867         {
8868                 if (ent->animcache_vertex3f && !r_framedata_failed)
8869                 {
8870                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8871                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8872                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8873                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8874                 }
8875                 else if (wanttangents)
8876                 {
8877                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8878                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
8879                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
8880                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8881                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
8882                 }
8883                 else if (wantnormals)
8884                 {
8885                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8886                         rsurface.modelsvector3f = NULL;
8887                         rsurface.modeltvector3f = NULL;
8888                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
8889                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
8890                 }
8891                 else
8892                 {
8893                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
8894                         rsurface.modelsvector3f = NULL;
8895                         rsurface.modeltvector3f = NULL;
8896                         rsurface.modelnormal3f = NULL;
8897                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
8898                 }
8899                 rsurface.modelvertex3f_bufferobject = 0;
8900                 rsurface.modelvertex3f_bufferoffset = 0;
8901                 rsurface.modelsvector3f_bufferobject = 0;
8902                 rsurface.modelsvector3f_bufferoffset = 0;
8903                 rsurface.modeltvector3f_bufferobject = 0;
8904                 rsurface.modeltvector3f_bufferoffset = 0;
8905                 rsurface.modelnormal3f_bufferobject = 0;
8906                 rsurface.modelnormal3f_bufferoffset = 0;
8907                 rsurface.generatedvertex = true;
8908         }
8909         else
8910         {
8911                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8912                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
8913                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8914                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8915                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
8916                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8917                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8918                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
8919                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8920                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8921                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
8922                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8923                 rsurface.generatedvertex = false;
8924         }
8925         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8926         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
8927         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8928         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8929         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
8930         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8931         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8932         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
8933         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8934         rsurface.modelelement3i = model->surfmesh.data_element3i;
8935         rsurface.modelelement3s = model->surfmesh.data_element3s;
8936         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
8937         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
8938         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8939         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
8940         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
8941         rsurface.modelsurfaces = model->data_surfaces;
8942         rsurface.vertex3f  = rsurface.modelvertex3f;
8943         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
8944         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8945         rsurface.svector3f = rsurface.modelsvector3f;
8946         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
8947         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8948         rsurface.tvector3f = rsurface.modeltvector3f;
8949         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
8950         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8951         rsurface.normal3f  = rsurface.modelnormal3f;
8952         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
8953         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8954         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
8955 }
8956
8957 void RSurf_ActiveCustomEntity(const matrix4x4_t *matrix, const matrix4x4_t *inversematrix, int entflags, double shadertime, float r, float g, float b, float a, int numvertices, const float *vertex3f, const float *texcoord2f, const float *normal3f, const float *svector3f, const float *tvector3f, const float *color4f, int numtriangles, const int *element3i, const unsigned short *element3s, qboolean wantnormals, qboolean wanttangents)
8958 {
8959         rsurface.entity = r_refdef.scene.worldentity;
8960         rsurface.skeleton = NULL;
8961         rsurface.ent_skinnum = 0;
8962         rsurface.ent_qwskin = -1;
8963         rsurface.ent_shadertime = shadertime;
8964         rsurface.ent_flags = entflags;
8965         rsurface.modelnum_vertices = numvertices;
8966         rsurface.modelnum_triangles = numtriangles;
8967         if (rsurface.array_size < rsurface.modelnum_vertices)
8968                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
8969         rsurface.matrix = *matrix;
8970         rsurface.inversematrix = *inversematrix;
8971         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8972         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8973         R_EntityMatrix(&rsurface.matrix);
8974         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8975         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8976         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8977         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8978         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8979         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8980         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8981         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8982         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8983         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8984         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8985         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8986         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8987         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8988         rsurface.frameblend[0].lerp = 1;
8989         rsurface.ent_alttextures = false;
8990         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8991         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8992         if (wanttangents)
8993         {
8994                 rsurface.modelvertex3f = vertex3f;
8995                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
8996                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
8997                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
8998         }
8999         else if (wantnormals)
9000         {
9001                 rsurface.modelvertex3f = vertex3f;
9002                 rsurface.modelsvector3f = NULL;
9003                 rsurface.modeltvector3f = NULL;
9004                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9005         }
9006         else
9007         {
9008                 rsurface.modelvertex3f = vertex3f;
9009                 rsurface.modelsvector3f = NULL;
9010                 rsurface.modeltvector3f = NULL;
9011                 rsurface.modelnormal3f = NULL;
9012         }
9013         rsurface.modelvertex3f_bufferobject = 0;
9014         rsurface.modelvertex3f_bufferoffset = 0;
9015         rsurface.modelsvector3f_bufferobject = 0;
9016         rsurface.modelsvector3f_bufferoffset = 0;
9017         rsurface.modeltvector3f_bufferobject = 0;
9018         rsurface.modeltvector3f_bufferoffset = 0;
9019         rsurface.modelnormal3f_bufferobject = 0;
9020         rsurface.modelnormal3f_bufferoffset = 0;
9021         rsurface.generatedvertex = true;
9022         rsurface.modellightmapcolor4f  = color4f;
9023         rsurface.modellightmapcolor4f_bufferobject = 0;
9024         rsurface.modellightmapcolor4f_bufferoffset = 0;
9025         rsurface.modeltexcoordtexture2f  = texcoord2f;
9026         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9027         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9028         rsurface.modeltexcoordlightmap2f  = NULL;
9029         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9030         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9031         rsurface.modelelement3i = element3i;
9032         rsurface.modelelement3s = element3s;
9033         rsurface.modelelement3i_bufferobject = 0;
9034         rsurface.modelelement3s_bufferobject = 0;
9035         rsurface.modellightmapoffsets = NULL;
9036         rsurface.modelsurfaces = NULL;
9037         rsurface.vertex3f  = rsurface.modelvertex3f;
9038         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9039         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9040         rsurface.svector3f = rsurface.modelsvector3f;
9041         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9042         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9043         rsurface.tvector3f = rsurface.modeltvector3f;
9044         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9045         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9046         rsurface.normal3f  = rsurface.modelnormal3f;
9047         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9048         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9049         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9050
9051         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9052         {
9053                 if ((wantnormals || wanttangents) && !normal3f)
9054                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9055                 if (wanttangents && !svector3f)
9056                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9057         }
9058 }
9059
9060 float RSurf_FogPoint(const float *v)
9061 {
9062         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9063         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9064         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9065         float FogHeightFade = r_refdef.fogheightfade;
9066         float fogfrac;
9067         unsigned int fogmasktableindex;
9068         if (r_refdef.fogplaneviewabove)
9069                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9070         else
9071                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9072         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9073         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9074 }
9075
9076 float RSurf_FogVertex(const float *v)
9077 {
9078         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9079         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9080         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9081         float FogHeightFade = rsurface.fogheightfade;
9082         float fogfrac;
9083         unsigned int fogmasktableindex;
9084         if (r_refdef.fogplaneviewabove)
9085                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9086         else
9087                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9088         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9089         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9090 }
9091
9092 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9093 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9094 {
9095         int deformindex;
9096         int texturesurfaceindex;
9097         int i, j;
9098         float amplitude;
9099         float animpos;
9100         float scale;
9101         const float *v1, *in_tc;
9102         float *out_tc;
9103         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9104         float waveparms[4];
9105         q3shaderinfo_deform_t *deform;
9106         // if vertices are dynamic (animated models), generate them into the temporary rsurface.array_model* arrays and point rsurface.model* at them instead of the static data from the model itself
9107         if (rsurface.generatedvertex)
9108         {
9109                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9110                         generatenormals = true;
9111                 for (i = 0;i < Q3MAXDEFORMS;i++)
9112                 {
9113                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9114                         {
9115                                 generatetangents = true;
9116                                 generatenormals = true;
9117                         }
9118                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9119                                 generatenormals = true;
9120                 }
9121                 if (generatenormals && !rsurface.modelnormal3f)
9122                 {
9123                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9124                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9125                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9126                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9127                 }
9128                 if (generatetangents && !rsurface.modelsvector3f)
9129                 {
9130                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9131                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9132                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9133                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9134                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9135                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9136                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9137                 }
9138         }
9139         rsurface.vertex3f  = rsurface.modelvertex3f;
9140         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9141         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9142         rsurface.svector3f = rsurface.modelsvector3f;
9143         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9144         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9145         rsurface.tvector3f = rsurface.modeltvector3f;
9146         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9147         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9148         rsurface.normal3f  = rsurface.modelnormal3f;
9149         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9150         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9151         // if vertices are deformed (sprite flares and things in maps, possibly
9152         // water waves, bulges and other deformations), generate them into
9153         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9154         // (may be static model data or generated data for an animated model, or
9155         //  the previous deform pass)
9156         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9157         {
9158                 switch (deform->deform)
9159                 {
9160                 default:
9161                 case Q3DEFORM_PROJECTIONSHADOW:
9162                 case Q3DEFORM_TEXT0:
9163                 case Q3DEFORM_TEXT1:
9164                 case Q3DEFORM_TEXT2:
9165                 case Q3DEFORM_TEXT3:
9166                 case Q3DEFORM_TEXT4:
9167                 case Q3DEFORM_TEXT5:
9168                 case Q3DEFORM_TEXT6:
9169                 case Q3DEFORM_TEXT7:
9170                 case Q3DEFORM_NONE:
9171                         break;
9172                 case Q3DEFORM_AUTOSPRITE:
9173                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9174                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9175                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9176                         VectorNormalize(newforward);
9177                         VectorNormalize(newright);
9178                         VectorNormalize(newup);
9179                         // make deformed versions of only the model vertices used by the specified surfaces
9180                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9181                         {
9182                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9183                                 // a single autosprite surface can contain multiple sprites...
9184                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9185                                 {
9186                                         VectorClear(center);
9187                                         for (i = 0;i < 4;i++)
9188                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9189                                         VectorScale(center, 0.25f, center);
9190                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9191                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9192                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9193                                         for (i = 0;i < 4;i++)
9194                                         {
9195                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9196                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9197                                         }
9198                                 }
9199                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9200                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9201                         }
9202                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9203                         rsurface.vertex3f_bufferobject = 0;
9204                         rsurface.vertex3f_bufferoffset = 0;
9205                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9206                         rsurface.svector3f_bufferobject = 0;
9207                         rsurface.svector3f_bufferoffset = 0;
9208                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9209                         rsurface.tvector3f_bufferobject = 0;
9210                         rsurface.tvector3f_bufferoffset = 0;
9211                         rsurface.normal3f = rsurface.array_deformednormal3f;
9212                         rsurface.normal3f_bufferobject = 0;
9213                         rsurface.normal3f_bufferoffset = 0;
9214                         break;
9215                 case Q3DEFORM_AUTOSPRITE2:
9216                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9217                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9218                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9219                         VectorNormalize(newforward);
9220                         VectorNormalize(newright);
9221                         VectorNormalize(newup);
9222                         // make deformed versions of only the model vertices used by the specified surfaces
9223                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9224                         {
9225                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9226                                 const float *v1, *v2;
9227                                 vec3_t start, end;
9228                                 float f, l;
9229                                 struct
9230                                 {
9231                                         float length2;
9232                                         const float *v1;
9233                                         const float *v2;
9234                                 }
9235                                 shortest[2];
9236                                 memset(shortest, 0, sizeof(shortest));
9237                                 // a single autosprite surface can contain multiple sprites...
9238                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9239                                 {
9240                                         VectorClear(center);
9241                                         for (i = 0;i < 4;i++)
9242                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9243                                         VectorScale(center, 0.25f, center);
9244                                         // find the two shortest edges, then use them to define the
9245                                         // axis vectors for rotating around the central axis
9246                                         for (i = 0;i < 6;i++)
9247                                         {
9248                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9249                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9250 #if 0
9251                                                 Debug_PolygonBegin(NULL, 0);
9252                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9253                                                 Debug_PolygonVertex((v1[0] + v2[0]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, (v1[1] + v2[1]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1], (v1[2] + v2[2]) * 0.5f + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2], 0, 0, 1, 1, 0, 1);
9254                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9255                                                 Debug_PolygonEnd();
9256 #endif
9257                                                 l = VectorDistance2(v1, v2);
9258                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9259                                                 if (v1[2] != v2[2])
9260                                                         l += (1.0f / 1024.0f);
9261                                                 if (shortest[0].length2 > l || i == 0)
9262                                                 {
9263                                                         shortest[1] = shortest[0];
9264                                                         shortest[0].length2 = l;
9265                                                         shortest[0].v1 = v1;
9266                                                         shortest[0].v2 = v2;
9267                                                 }
9268                                                 else if (shortest[1].length2 > l || i == 1)
9269                                                 {
9270                                                         shortest[1].length2 = l;
9271                                                         shortest[1].v1 = v1;
9272                                                         shortest[1].v2 = v2;
9273                                                 }
9274                                         }
9275                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9276                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9277 #if 0
9278                                         Debug_PolygonBegin(NULL, 0);
9279                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9280                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 4, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 4, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 4, 0, 0, 0, 1, 0, 1);
9281                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9282                                         Debug_PolygonEnd();
9283 #endif
9284                                         // this calculates the right vector from the shortest edge
9285                                         // and the up vector from the edge midpoints
9286                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9287                                         VectorNormalize(right);
9288                                         VectorSubtract(end, start, up);
9289                                         VectorNormalize(up);
9290                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9291                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9292                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9293                                         VectorNegate(forward, forward);
9294                                         VectorReflect(forward, 0, up, forward);
9295                                         VectorNormalize(forward);
9296                                         CrossProduct(up, forward, newright);
9297                                         VectorNormalize(newright);
9298 #if 0
9299                                         Debug_PolygonBegin(NULL, 0);
9300                                         Debug_PolygonVertex(center[0] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+0] * 8, center[1] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+1] * 8, center[2] + rsurface.normal3f[3 * (surface->num_firstvertex + j)+2] * 8, 0, 0, 1, 0, 0, 1);
9301                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9302                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9303                                         Debug_PolygonEnd();
9304 #endif
9305 #if 0
9306                                         Debug_PolygonBegin(NULL, 0);
9307                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9308                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9309                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9310                                         Debug_PolygonEnd();
9311 #endif
9312                                         // rotate the quad around the up axis vector, this is made
9313                                         // especially easy by the fact we know the quad is flat,
9314                                         // so we only have to subtract the center position and
9315                                         // measure distance along the right vector, and then
9316                                         // multiply that by the newright vector and add back the
9317                                         // center position
9318                                         // we also need to subtract the old position to undo the
9319                                         // displacement from the center, which we do with a
9320                                         // DotProduct, the subtraction/addition of center is also
9321                                         // optimized into DotProducts here
9322                                         l = DotProduct(right, center);
9323                                         for (i = 0;i < 4;i++)
9324                                         {
9325                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9326                                                 f = DotProduct(right, v1) - l;
9327                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9328                                         }
9329                                 }
9330                                 Mod_BuildNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformednormal3f, r_smoothnormals_areaweighting.integer != 0);
9331                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9332                         }
9333                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9334                         rsurface.vertex3f_bufferobject = 0;
9335                         rsurface.vertex3f_bufferoffset = 0;
9336                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9337                         rsurface.svector3f_bufferobject = 0;
9338                         rsurface.svector3f_bufferoffset = 0;
9339                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9340                         rsurface.tvector3f_bufferobject = 0;
9341                         rsurface.tvector3f_bufferoffset = 0;
9342                         rsurface.normal3f = rsurface.array_deformednormal3f;
9343                         rsurface.normal3f_bufferobject = 0;
9344                         rsurface.normal3f_bufferoffset = 0;
9345                         break;
9346                 case Q3DEFORM_NORMAL:
9347                         // deform the normals to make reflections wavey
9348                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9349                         {
9350                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9351                                 for (j = 0;j < surface->num_vertices;j++)
9352                                 {
9353                                         float vertex[3];
9354                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9355                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9356                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9357                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9358                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9359                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9360                                         VectorNormalize(normal);
9361                                 }
9362                                 Mod_BuildTextureVectorsFromNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface.vertex3f, rsurface.modeltexcoordtexture2f, rsurface.array_deformednormal3f, rsurface.modelelement3i + surface->num_firsttriangle * 3, rsurface.array_deformedsvector3f, rsurface.array_deformedtvector3f, r_smoothnormals_areaweighting.integer != 0);
9363                         }
9364                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9365                         rsurface.svector3f_bufferobject = 0;
9366                         rsurface.svector3f_bufferoffset = 0;
9367                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9368                         rsurface.tvector3f_bufferobject = 0;
9369                         rsurface.tvector3f_bufferoffset = 0;
9370                         rsurface.normal3f = rsurface.array_deformednormal3f;
9371                         rsurface.normal3f_bufferobject = 0;
9372                         rsurface.normal3f_bufferoffset = 0;
9373                         break;
9374                 case Q3DEFORM_WAVE:
9375                         // deform vertex array to make wavey water and flags and such
9376                         waveparms[0] = deform->waveparms[0];
9377                         waveparms[1] = deform->waveparms[1];
9378                         waveparms[2] = deform->waveparms[2];
9379                         waveparms[3] = deform->waveparms[3];
9380                         // this is how a divisor of vertex influence on deformation
9381                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9382                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9383                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9384                         {
9385                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9386                                 for (j = 0;j < surface->num_vertices;j++)
9387                                 {
9388                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9389                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9390                                         // if the wavefunc depends on time, evaluate it per-vertex
9391                                         if (waveparms[3])
9392                                         {
9393                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9394                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9395                                         }
9396                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9397                                 }
9398                         }
9399                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9400                         rsurface.vertex3f_bufferobject = 0;
9401                         rsurface.vertex3f_bufferoffset = 0;
9402                         break;
9403                 case Q3DEFORM_BULGE:
9404                         // deform vertex array to make the surface have moving bulges
9405                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9406                         {
9407                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9408                                 for (j = 0;j < surface->num_vertices;j++)
9409                                 {
9410                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9411                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9412                                 }
9413                         }
9414                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9415                         rsurface.vertex3f_bufferobject = 0;
9416                         rsurface.vertex3f_bufferoffset = 0;
9417                         break;
9418                 case Q3DEFORM_MOVE:
9419                         // deform vertex array
9420                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9421                         VectorScale(deform->parms, scale, waveparms);
9422                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9423                         {
9424                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9425                                 for (j = 0;j < surface->num_vertices;j++)
9426                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9427                         }
9428                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9429                         rsurface.vertex3f_bufferobject = 0;
9430                         rsurface.vertex3f_bufferoffset = 0;
9431                         break;
9432                 }
9433         }
9434         // generate texcoords based on the chosen texcoord source
9435         switch(rsurface.texture->tcgen.tcgen)
9436         {
9437         default:
9438         case Q3TCGEN_TEXTURE:
9439                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9440                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9441                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9442                 break;
9443         case Q3TCGEN_LIGHTMAP:
9444                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9445                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9446                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9447                 break;
9448         case Q3TCGEN_VECTOR:
9449                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9450                 {
9451                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9452                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, out_tc += 2)
9453                         {
9454                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9455                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9456                         }
9457                 }
9458                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9459                 rsurface.texcoordtexture2f_bufferobject  = 0;
9460                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9461                 break;
9462         case Q3TCGEN_ENVIRONMENT:
9463                 // make environment reflections using a spheremap
9464                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9465                 {
9466                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9467                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9468                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9469                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9470                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9471                         {
9472                                 // identical to Q3A's method, but executed in worldspace so
9473                                 // carried models can be shiny too
9474
9475                                 float viewer[3], d, reflected[3], worldreflected[3];
9476
9477                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
9478                                 // VectorNormalize(viewer);
9479
9480                                 d = DotProduct(normal, viewer);
9481
9482                                 reflected[0] = normal[0]*2*d - viewer[0];
9483                                 reflected[1] = normal[1]*2*d - viewer[1];
9484                                 reflected[2] = normal[2]*2*d - viewer[2];
9485                                 // note: this is proportinal to viewer, so we can normalize later
9486
9487                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9488                                 VectorNormalize(worldreflected);
9489
9490                                 // note: this sphere map only uses world x and z!
9491                                 // so positive and negative y will LOOK THE SAME.
9492                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
9493                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
9494                         }
9495                 }
9496                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9497                 rsurface.texcoordtexture2f_bufferobject  = 0;
9498                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9499                 break;
9500         }
9501         // the only tcmod that needs software vertex processing is turbulent, so
9502         // check for it here and apply the changes if needed
9503         // and we only support that as the first one
9504         // (handling a mixture of turbulent and other tcmods would be problematic
9505         //  without punting it entirely to a software path)
9506         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9507         {
9508                 amplitude = rsurface.texture->tcmods[0].parms[1];
9509                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
9510                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9511                 {
9512                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9513                         for (j = 0, v1 = rsurface.modelvertex3f + 3 * surface->num_firstvertex, in_tc = rsurface.texcoordtexture2f + 2 * surface->num_firstvertex, out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;j < surface->num_vertices;j++, v1 += 3, in_tc += 2, out_tc += 2)
9514                         {
9515                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9516                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9517                         }
9518                 }
9519                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9520                 rsurface.texcoordtexture2f_bufferobject  = 0;
9521                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9522         }
9523         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
9524         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
9525         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9526         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
9527 }
9528
9529 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9530 {
9531         int i, j;
9532         const msurface_t *surface = texturesurfacelist[0];
9533         const msurface_t *surface2;
9534         int firstvertex;
9535         int endvertex;
9536         int numvertices;
9537         int numtriangles;
9538         // TODO: lock all array ranges before render, rather than on each surface
9539         if (texturenumsurfaces == 1)
9540         {
9541                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9542                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9543         }
9544         else if (r_batchmode.integer == 2)
9545         {
9546                 #define MAXBATCHTRIANGLES 4096
9547                 int batchtriangles = 0;
9548                 static int batchelements[MAXBATCHTRIANGLES*3];
9549                 for (i = 0;i < texturenumsurfaces;i = j)
9550                 {
9551                         surface = texturesurfacelist[i];
9552                         j = i + 1;
9553                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9554                         {
9555                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9556                                 continue;
9557                         }
9558                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9559                         batchtriangles = surface->num_triangles;
9560                         firstvertex = surface->num_firstvertex;
9561                         endvertex = surface->num_firstvertex + surface->num_vertices;
9562                         for (;j < texturenumsurfaces;j++)
9563                         {
9564                                 surface2 = texturesurfacelist[j];
9565                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9566                                         break;
9567                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9568                                 batchtriangles += surface2->num_triangles;
9569                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9570                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9571                         }
9572                         surface2 = texturesurfacelist[j-1];
9573                         numvertices = endvertex - firstvertex;
9574                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9575                 }
9576         }
9577         else if (r_batchmode.integer == 1)
9578         {
9579                 for (i = 0;i < texturenumsurfaces;i = j)
9580                 {
9581                         surface = texturesurfacelist[i];
9582                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9583                                 if (texturesurfacelist[j] != surface2)
9584                                         break;
9585                         surface2 = texturesurfacelist[j-1];
9586                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9587                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9588                         GL_LockArrays(surface->num_firstvertex, numvertices);
9589                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9590                 }
9591         }
9592         else
9593         {
9594                 for (i = 0;i < texturenumsurfaces;i++)
9595                 {
9596                         surface = texturesurfacelist[i];
9597                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9598                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9599                 }
9600         }
9601 }
9602
9603 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
9604 {
9605         switch(vid.renderpath)
9606         {
9607         case RENDERPATH_CGGL:
9608 #ifdef SUPPORTCG
9609                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
9610                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
9611 #endif
9612                 break;
9613         case RENDERPATH_GL20:
9614                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
9615                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
9616                 break;
9617         case RENDERPATH_GL13:
9618         case RENDERPATH_GL11:
9619                 R_Mesh_TexBind(0, surface->lightmaptexture);
9620                 break;
9621         }
9622 }
9623
9624 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
9625 {
9626         // pick the closest matching water plane and bind textures
9627         int planeindex, vertexindex;
9628         float d, bestd;
9629         vec3_t vert;
9630         const float *v;
9631         r_waterstate_waterplane_t *p, *bestp;
9632         bestd = 0;
9633         bestp = NULL;
9634         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9635         {
9636                 d = 0;
9637                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
9638                 {
9639                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9640                         d += fabs(PlaneDiff(vert, &p->plane));
9641                 }
9642                 if (bestd > d || !bestp)
9643                 {
9644                         bestd = d;
9645                         bestp = p;
9646                 }
9647         }
9648         switch(vid.renderpath)
9649         {
9650         case RENDERPATH_CGGL:
9651 #ifdef SUPPORTCG
9652                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
9653                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
9654 #endif
9655                 break;
9656         case RENDERPATH_GL20:
9657                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
9658                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
9659                 break;
9660         case RENDERPATH_GL13:
9661         case RENDERPATH_GL11:
9662                 break;
9663         }
9664 }
9665
9666 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9667 {
9668         int i;
9669         const msurface_t *surface;
9670         if (r_waterstate.renderingscene)
9671                 return;
9672         for (i = 0;i < texturenumsurfaces;i++)
9673         {
9674                 surface = texturesurfacelist[i];
9675                 RSurf_BindLightmapForSurface(surface);
9676                 RSurf_BindReflectionForSurface(surface);
9677                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9678                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9679         }
9680 }
9681
9682 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9683 {
9684         int i;
9685         int j;
9686         const msurface_t *surface = texturesurfacelist[0];
9687         const msurface_t *surface2;
9688         int firstvertex;
9689         int endvertex;
9690         int numvertices;
9691         int numtriangles;
9692         if (texturenumsurfaces == 1)
9693         {
9694                 RSurf_BindLightmapForSurface(surface);
9695                 GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9696                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9697         }
9698         else if (r_batchmode.integer == 2)
9699         {
9700 #define MAXBATCHTRIANGLES 4096
9701                 int batchtriangles = 0;
9702                 static int batchelements[MAXBATCHTRIANGLES*3];
9703                 for (i = 0;i < texturenumsurfaces;i = j)
9704                 {
9705                         surface = texturesurfacelist[i];
9706                         RSurf_BindLightmapForSurface(surface);
9707                         j = i + 1;
9708                         if (surface->num_triangles > MAXBATCHTRIANGLES)
9709                         {
9710                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9711                                 continue;
9712                         }
9713                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
9714                         batchtriangles = surface->num_triangles;
9715                         firstvertex = surface->num_firstvertex;
9716                         endvertex = surface->num_firstvertex + surface->num_vertices;
9717                         for (;j < texturenumsurfaces;j++)
9718                         {
9719                                 surface2 = texturesurfacelist[j];
9720                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
9721                                         break;
9722                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
9723                                 batchtriangles += surface2->num_triangles;
9724                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
9725                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
9726                         }
9727                         surface2 = texturesurfacelist[j-1];
9728                         numvertices = endvertex - firstvertex;
9729                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
9730                 }
9731         }
9732         else if (r_batchmode.integer == 1)
9733         {
9734 #if 0
9735                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
9736                 for (i = 0;i < texturenumsurfaces;i = j)
9737                 {
9738                         surface = texturesurfacelist[i];
9739                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9740                                 if (texturesurfacelist[j] != surface2)
9741                                         break;
9742                         Con_Printf(" %i", j - i);
9743                 }
9744                 Con_Printf("\n");
9745                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
9746 #endif
9747                 for (i = 0;i < texturenumsurfaces;i = j)
9748                 {
9749                         surface = texturesurfacelist[i];
9750                         RSurf_BindLightmapForSurface(surface);
9751                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
9752                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
9753                                         break;
9754 #if 0
9755                         Con_Printf(" %i", j - i);
9756 #endif
9757                         surface2 = texturesurfacelist[j-1];
9758                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
9759                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
9760                         GL_LockArrays(surface->num_firstvertex, numvertices);
9761                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9762                 }
9763 #if 0
9764                 Con_Printf("\n");
9765 #endif
9766         }
9767         else
9768         {
9769                 for (i = 0;i < texturenumsurfaces;i++)
9770                 {
9771                         surface = texturesurfacelist[i];
9772                         RSurf_BindLightmapForSurface(surface);
9773                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9774                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9775                 }
9776         }
9777 }
9778
9779 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9780 {
9781         int j;
9782         int texturesurfaceindex;
9783         if (r_showsurfaces.integer == 2)
9784         {
9785                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9786                 {
9787                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9788                         for (j = 0;j < surface->num_triangles;j++)
9789                         {
9790                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
9791                                 GL_Color(f, f, f, 1);
9792                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9793                         }
9794                 }
9795         }
9796         else
9797         {
9798                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9799                 {
9800                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9801                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
9802                         GL_Color((k & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 4) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, ((k >> 8) & 15) * (1.0f / 16.0f) * r_refdef.view.colorscale, 1);
9803                         GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
9804                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
9805                 }
9806         }
9807 }
9808
9809 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9810 {
9811         int texturesurfaceindex;
9812         int i;
9813         const float *v;
9814         float *c2;
9815         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9816         {
9817                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9818                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
9819                 {
9820                         c2[0] = 0.5;
9821                         c2[1] = 0.5;
9822                         c2[2] = 0.5;
9823                         c2[3] = 1;
9824                 }
9825         }
9826         rsurface.lightmapcolor4f = rsurface.array_color4f;
9827         rsurface.lightmapcolor4f_bufferobject = 0;
9828         rsurface.lightmapcolor4f_bufferoffset = 0;
9829 }
9830
9831 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9832 {
9833         int texturesurfaceindex;
9834         int i;
9835         float f;
9836         const float *v;
9837         const float *c;
9838         float *c2;
9839         if (rsurface.lightmapcolor4f)
9840         {
9841                 // generate color arrays for the surfaces in this list
9842                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9843                 {
9844                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9845                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
9846                         {
9847                                 f = RSurf_FogVertex(v);
9848                                 c2[0] = c[0] * f;
9849                                 c2[1] = c[1] * f;
9850                                 c2[2] = c[2] * f;
9851                                 c2[3] = c[3];
9852                         }
9853                 }
9854         }
9855         else
9856         {
9857                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9858                 {
9859                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9860                         for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c2 += 4)
9861                         {
9862                                 f = RSurf_FogVertex(v);
9863                                 c2[0] = f;
9864                                 c2[1] = f;
9865                                 c2[2] = f;
9866                                 c2[3] = 1;
9867                         }
9868                 }
9869         }
9870         rsurface.lightmapcolor4f = rsurface.array_color4f;
9871         rsurface.lightmapcolor4f_bufferobject = 0;
9872         rsurface.lightmapcolor4f_bufferoffset = 0;
9873 }
9874
9875 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9876 {
9877         int texturesurfaceindex;
9878         int i;
9879         float f;
9880         const float *v;
9881         const float *c;
9882         float *c2;
9883         if (!rsurface.lightmapcolor4f)
9884                 return;
9885         // generate color arrays for the surfaces in this list
9886         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9887         {
9888                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9889                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4, c2 += 4)
9890                 {
9891                         f = RSurf_FogVertex(v);
9892                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9893                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9894                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9895                         c2[3] = c[3];
9896                 }
9897         }
9898         rsurface.lightmapcolor4f = rsurface.array_color4f;
9899         rsurface.lightmapcolor4f_bufferobject = 0;
9900         rsurface.lightmapcolor4f_bufferoffset = 0;
9901 }
9902
9903 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
9904 {
9905         int texturesurfaceindex;
9906         int i;
9907         const float *c;
9908         float *c2;
9909         if (!rsurface.lightmapcolor4f)
9910                 return;
9911         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9912         {
9913                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9914                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
9915                 {
9916                         c2[0] = c[0] * r;
9917                         c2[1] = c[1] * g;
9918                         c2[2] = c[2] * b;
9919                         c2[3] = c[3] * a;
9920                 }
9921         }
9922         rsurface.lightmapcolor4f = rsurface.array_color4f;
9923         rsurface.lightmapcolor4f_bufferobject = 0;
9924         rsurface.lightmapcolor4f_bufferoffset = 0;
9925 }
9926
9927 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9928 {
9929         int texturesurfaceindex;
9930         int i;
9931         const float *c;
9932         float *c2;
9933         if (!rsurface.lightmapcolor4f)
9934                 return;
9935         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9936         {
9937                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9938                 for (i = 0, c = (rsurface.lightmapcolor4f + 4 * surface->num_firstvertex), c2 = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, c += 4, c2 += 4)
9939                 {
9940                         c2[0] = c[0] + r_refdef.scene.ambient;
9941                         c2[1] = c[1] + r_refdef.scene.ambient;
9942                         c2[2] = c[2] + r_refdef.scene.ambient;
9943                         c2[3] = c[3];
9944                 }
9945         }
9946         rsurface.lightmapcolor4f = rsurface.array_color4f;
9947         rsurface.lightmapcolor4f_bufferobject = 0;
9948         rsurface.lightmapcolor4f_bufferoffset = 0;
9949 }
9950
9951 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9952 {
9953         // TODO: optimize
9954         rsurface.lightmapcolor4f = NULL;
9955         rsurface.lightmapcolor4f_bufferobject = 0;
9956         rsurface.lightmapcolor4f_bufferoffset = 0;
9957         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9958         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9959         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9960         GL_Color(r, g, b, a);
9961         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
9962 }
9963
9964 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9965 {
9966         // TODO: optimize applyfog && applycolor case
9967         // just apply fog if necessary, and tint the fog color array if necessary
9968         rsurface.lightmapcolor4f = NULL;
9969         rsurface.lightmapcolor4f_bufferobject = 0;
9970         rsurface.lightmapcolor4f_bufferoffset = 0;
9971         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
9972         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
9973         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
9974         GL_Color(r, g, b, a);
9975         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
9976 }
9977
9978 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9979 {
9980         int texturesurfaceindex;
9981         int i;
9982         float *c;
9983         // TODO: optimize
9984         if (texturesurfacelist[0]->lightmapinfo)
9985         {
9986                 // generate color arrays for the surfaces in this list
9987                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9988                 {
9989                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9990                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
9991                         {
9992                                 if (surface->lightmapinfo->samples)
9993                                 {
9994                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
9995                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
9996                                         VectorScale(lm, scale, c);
9997                                         if (surface->lightmapinfo->styles[1] != 255)
9998                                         {
9999                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10000                                                 lm += size3;
10001                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10002                                                 VectorMA(c, scale, lm, c);
10003                                                 if (surface->lightmapinfo->styles[2] != 255)
10004                                                 {
10005                                                         lm += size3;
10006                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10007                                                         VectorMA(c, scale, lm, c);
10008                                                         if (surface->lightmapinfo->styles[3] != 255)
10009                                                         {
10010                                                                 lm += size3;
10011                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10012                                                                 VectorMA(c, scale, lm, c);
10013                                                         }
10014                                                 }
10015                                         }
10016                                 }
10017                                 else
10018                                         VectorClear(c);
10019                                 c[3] = 1;
10020                         }
10021                 }
10022                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10023                 rsurface.lightmapcolor4f_bufferobject = 0;
10024                 rsurface.lightmapcolor4f_bufferoffset = 0;
10025         }
10026         else
10027         {
10028                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10029                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10030                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10031         }
10032         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10033         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10034         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10035         GL_Color(r, g, b, a);
10036         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10037 }
10038
10039 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10040 {
10041         int texturesurfaceindex;
10042         int i;
10043         float f;
10044         float alpha;
10045         const float *v;
10046         const float *n;
10047         float *c;
10048         vec3_t ambientcolor;
10049         vec3_t diffusecolor;
10050         vec3_t lightdir;
10051         // TODO: optimize
10052         // model lighting
10053         VectorCopy(rsurface.modellight_lightdir, lightdir);
10054         f = 0.5f * r_refdef.lightmapintensity;
10055         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10056         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10057         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10058         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10059         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10060         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10061         alpha = *a;
10062         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10063         {
10064                 // generate color arrays for the surfaces in this list
10065                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10066                 {
10067                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10068                         int numverts = surface->num_vertices;
10069                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10070                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10071                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10072                         // q3-style directional shading
10073                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10074                         {
10075                                 if ((f = DotProduct(n, lightdir)) > 0)
10076                                         VectorMA(ambientcolor, f, diffusecolor, c);
10077                                 else
10078                                         VectorCopy(ambientcolor, c);
10079                                 c[3] = alpha;
10080                         }
10081                 }
10082                 *r = 1;
10083                 *g = 1;
10084                 *b = 1;
10085                 *a = 1;
10086                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10087                 rsurface.lightmapcolor4f_bufferobject = 0;
10088                 rsurface.lightmapcolor4f_bufferoffset = 0;
10089                 *applycolor = false;
10090         }
10091         else
10092         {
10093                 *r = ambientcolor[0];
10094                 *g = ambientcolor[1];
10095                 *b = ambientcolor[2];
10096                 rsurface.lightmapcolor4f = NULL;
10097                 rsurface.lightmapcolor4f_bufferobject = 0;
10098                 rsurface.lightmapcolor4f_bufferoffset = 0;
10099         }
10100 }
10101
10102 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10103 {
10104         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10105         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10106         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10107         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10108         GL_Color(r, g, b, a);
10109         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10110 }
10111
10112 void RSurf_SetupDepthAndCulling(void)
10113 {
10114         // submodels are biased to avoid z-fighting with world surfaces that they
10115         // may be exactly overlapping (avoids z-fighting artifacts on certain
10116         // doors and things in Quake maps)
10117         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10118         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10119         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10120         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10121 }
10122
10123 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10124 {
10125         // transparent sky would be ridiculous
10126         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10127                 return;
10128         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10129         skyrenderlater = true;
10130         RSurf_SetupDepthAndCulling();
10131         GL_DepthMask(true);
10132         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10133         // skymasking on them, and Quake3 never did sky masking (unlike
10134         // software Quake and software Quake2), so disable the sky masking
10135         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10136         // and skymasking also looks very bad when noclipping outside the
10137         // level, so don't use it then either.
10138         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10139         {
10140                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10141                 R_Mesh_ColorPointer(NULL, 0, 0);
10142                 R_Mesh_ResetTextureState();
10143                 if (skyrendermasked)
10144                 {
10145                         R_SetupShader_DepthOrShadow();
10146                         // depth-only (masking)
10147                         GL_ColorMask(0,0,0,0);
10148                         // just to make sure that braindead drivers don't draw
10149                         // anything despite that colormask...
10150                         GL_BlendFunc(GL_ZERO, GL_ONE);
10151                 }
10152                 else
10153                 {
10154                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10155                         // fog sky
10156                         GL_BlendFunc(GL_ONE, GL_ZERO);
10157                 }
10158                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10159                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10160                 if (skyrendermasked)
10161                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10162         }
10163         R_Mesh_ResetTextureState();
10164         GL_Color(1, 1, 1, 1);
10165 }
10166
10167 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10168 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10169 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10170 {
10171         qboolean reflect = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)) && !prepass;
10172         qboolean refract = (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !prepass;
10173
10174         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10175                 return;
10176
10177         if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10178                 R_Mesh_ColorPointer(NULL, 0, 0);
10179         else
10180                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10181
10182         if (refract)
10183         {
10184                 // render background
10185                 GL_BlendFunc(GL_ONE, GL_ZERO);
10186                 GL_DepthMask(true);
10187                 GL_AlphaTest(false);
10188
10189                 GL_Color(1, 1, 1, 1);
10190                 R_Mesh_ColorPointer(NULL, 0, 0);
10191
10192                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10193                 RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10194                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10195                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10196                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10197                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10198                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10199                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10200                 GL_LockArrays(0, 0);
10201
10202                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10203                 GL_DepthMask(false);
10204                 if ((rsurface.uselightmaptexture || (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND))
10205                         R_Mesh_ColorPointer(NULL, 0, 0);
10206                 else
10207                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
10208         }
10209
10210         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, prepass ? RSURFPASS_DEFERREDGEOMETRY : RSURFPASS_BASE);
10211
10212         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10213         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10214         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
10215         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
10216         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
10217         if (!prepass)
10218                 R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10219
10220         if (refract)
10221                 GL_DepthMask(true);
10222         else
10223                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10224         GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
10225         GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0 && !r_shadow_usingdeferredprepass);
10226
10227         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10228         {
10229                 if (refract || reflect)
10230                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10231                 else
10232                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10233         }
10234         else
10235         {
10236                 if (refract || reflect)
10237                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10238                 else
10239                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10240         }
10241         GL_LockArrays(0, 0);
10242 }
10243
10244 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10245 {
10246         // OpenGL 1.3 path - anything not completely ancient
10247         int texturesurfaceindex;
10248         qboolean applycolor;
10249         qboolean applyfog;
10250         int layerindex;
10251         const texturelayer_t *layer;
10252         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10253
10254         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10255         {
10256                 vec4_t layercolor;
10257                 int layertexrgbscale;
10258                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10259                 {
10260                         if (layerindex == 0)
10261                                 GL_AlphaTest(true);
10262                         else
10263                         {
10264                                 GL_AlphaTest(false);
10265                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10266                         }
10267                 }
10268                 GL_DepthMask(layer->depthmask && writedepth);
10269                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10270                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10271                 {
10272                         layertexrgbscale = 4;
10273                         VectorScale(layer->color, 0.25f, layercolor);
10274                 }
10275                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10276                 {
10277                         layertexrgbscale = 2;
10278                         VectorScale(layer->color, 0.5f, layercolor);
10279                 }
10280                 else
10281                 {
10282                         layertexrgbscale = 1;
10283                         VectorScale(layer->color, 1.0f, layercolor);
10284                 }
10285                 layercolor[3] = layer->color[3];
10286                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10287                 R_Mesh_ColorPointer(NULL, 0, 0);
10288                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10289                 switch (layer->type)
10290                 {
10291                 case TEXTURELAYERTYPE_LITTEXTURE:
10292                         // single-pass lightmapped texture with 2x rgbscale
10293                         //R_Mesh_TexBind(0, r_texture_white);
10294                         R_Mesh_TexMatrix(0, NULL);
10295                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10296                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10297                         R_Mesh_TexBind(1, layer->texture);
10298                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10299                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10300                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10301                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10302                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10303                         else if (rsurface.uselightmaptexture)
10304                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10305                         else
10306                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10307                         break;
10308                 case TEXTURELAYERTYPE_TEXTURE:
10309                         // singletexture unlit texture with transparency support
10310                         R_Mesh_TexBind(0, layer->texture);
10311                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10312                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10313                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10314                         R_Mesh_TexBind(1, 0);
10315                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10316                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10317                         break;
10318                 case TEXTURELAYERTYPE_FOG:
10319                         // singletexture fogging
10320                         if (layer->texture)
10321                         {
10322                                 R_Mesh_TexBind(0, layer->texture);
10323                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10324                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10325                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10326                         }
10327                         else
10328                         {
10329                                 R_Mesh_TexBind(0, 0);
10330                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10331                         }
10332                         R_Mesh_TexBind(1, 0);
10333                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10334                         // generate a color array for the fog pass
10335                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10336                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10337                         {
10338                                 int i;
10339                                 float f;
10340                                 const float *v;
10341                                 float *c;
10342                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10343                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10344                                 {
10345                                         f = 1 - RSurf_FogVertex(v);
10346                                         c[0] = layercolor[0];
10347                                         c[1] = layercolor[1];
10348                                         c[2] = layercolor[2];
10349                                         c[3] = f * layercolor[3];
10350                                 }
10351                         }
10352                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10353                         break;
10354                 default:
10355                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10356                 }
10357                 GL_LockArrays(0, 0);
10358         }
10359         CHECKGLERROR
10360         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10361         {
10362                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10363                 GL_AlphaTest(false);
10364         }
10365 }
10366
10367 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10368 {
10369         // OpenGL 1.1 - crusty old voodoo path
10370         int texturesurfaceindex;
10371         qboolean applyfog;
10372         int layerindex;
10373         const texturelayer_t *layer;
10374         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10375
10376         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10377         {
10378                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10379                 {
10380                         if (layerindex == 0)
10381                                 GL_AlphaTest(true);
10382                         else
10383                         {
10384                                 GL_AlphaTest(false);
10385                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10386                         }
10387                 }
10388                 GL_DepthMask(layer->depthmask && writedepth);
10389                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10390                 R_Mesh_ColorPointer(NULL, 0, 0);
10391                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10392                 switch (layer->type)
10393                 {
10394                 case TEXTURELAYERTYPE_LITTEXTURE:
10395                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10396                         {
10397                                 // two-pass lit texture with 2x rgbscale
10398                                 // first the lightmap pass
10399                                 //R_Mesh_TexBind(0, r_texture_white);
10400                                 R_Mesh_TexMatrix(0, NULL);
10401                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10402                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10403                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10404                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10405                                 else if (rsurface.uselightmaptexture)
10406                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10407                                 else
10408                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10409                                 GL_LockArrays(0, 0);
10410                                 // then apply the texture to it
10411                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10412                                 R_Mesh_TexBind(0, layer->texture);
10413                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10414                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10415                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10416                                 RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0] * 0.5f, layer->color[1] * 0.5f, layer->color[2] * 0.5f, layer->color[3], layer->color[0] != 2 || layer->color[1] != 2 || layer->color[2] != 2 || layer->color[3] != 1, false);
10417                         }
10418                         else
10419                         {
10420                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10421                                 R_Mesh_TexBind(0, layer->texture);
10422                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10423                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10424                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10425                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10426                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10427                                 else
10428                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10429                         }
10430                         break;
10431                 case TEXTURELAYERTYPE_TEXTURE:
10432                         // singletexture unlit texture with transparency support
10433                         R_Mesh_TexBind(0, layer->texture);
10434                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10435                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10436                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10437                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layer->color[0], layer->color[1], layer->color[2], layer->color[3], layer->color[0] != 1 || layer->color[1] != 1 || layer->color[2] != 1 || layer->color[3] != 1, applyfog);
10438                         break;
10439                 case TEXTURELAYERTYPE_FOG:
10440                         // singletexture fogging
10441                         if (layer->texture)
10442                         {
10443                                 R_Mesh_TexBind(0, layer->texture);
10444                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10445                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10446                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10447                         }
10448                         else
10449                         {
10450                                 R_Mesh_TexBind(0, 0);
10451                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10452                         }
10453                         // generate a color array for the fog pass
10454                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10455                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10456                         {
10457                                 int i;
10458                                 float f;
10459                                 const float *v;
10460                                 float *c;
10461                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10462                                 for (i = 0, v = (rsurface.vertex3f + 3 * surface->num_firstvertex), c = (rsurface.array_color4f + 4 * surface->num_firstvertex);i < surface->num_vertices;i++, v += 3, c += 4)
10463                                 {
10464                                         f = 1 - RSurf_FogVertex(v);
10465                                         c[0] = layer->color[0];
10466                                         c[1] = layer->color[1];
10467                                         c[2] = layer->color[2];
10468                                         c[3] = f * layer->color[3];
10469                                 }
10470                         }
10471                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10472                         break;
10473                 default:
10474                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10475                 }
10476                 GL_LockArrays(0, 0);
10477         }
10478         CHECKGLERROR
10479         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10480         {
10481                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10482                 GL_AlphaTest(false);
10483         }
10484 }
10485
10486 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10487 {
10488         float c[4];
10489
10490         GL_AlphaTest(false);
10491         R_Mesh_ColorPointer(NULL, 0, 0);
10492         R_Mesh_ResetTextureState();
10493         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10494
10495         if(rsurface.texture && rsurface.texture->currentskinframe)
10496         {
10497                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10498                 c[3] *= rsurface.texture->currentalpha;
10499         }
10500         else
10501         {
10502                 c[0] = 1;
10503                 c[1] = 0;
10504                 c[2] = 1;
10505                 c[3] = 1;
10506         }
10507
10508         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10509         {
10510                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10511                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10512                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10513         }
10514
10515         // brighten it up (as texture value 127 means "unlit")
10516         c[0] *= 2 * r_refdef.view.colorscale;
10517         c[1] *= 2 * r_refdef.view.colorscale;
10518         c[2] *= 2 * r_refdef.view.colorscale;
10519
10520         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10521                 c[3] *= r_wateralpha.value;
10522
10523         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10524         {
10525                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10526                 GL_DepthMask(false);
10527         }
10528         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10529         {
10530                 GL_BlendFunc(GL_ONE, GL_ONE);
10531                 GL_DepthMask(false);
10532         }
10533         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10534         {
10535                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10536                 GL_DepthMask(false);
10537         }
10538         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10539         {
10540                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10541                 GL_DepthMask(false);
10542         }
10543         else
10544         {
10545                 GL_BlendFunc(GL_ONE, GL_ZERO);
10546                 GL_DepthMask(writedepth);
10547         }
10548
10549         rsurface.lightmapcolor4f = NULL;
10550
10551         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10552         {
10553                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10554
10555                 rsurface.lightmapcolor4f = NULL;
10556                 rsurface.lightmapcolor4f_bufferobject = 0;
10557                 rsurface.lightmapcolor4f_bufferoffset = 0;
10558         }
10559         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10560         {
10561                 qboolean applycolor = true;
10562                 float one = 1.0;
10563
10564                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10565
10566                 r_refdef.lightmapintensity = 1;
10567                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
10568                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10569         }
10570         else
10571         {
10572                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10573
10574                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10575                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10576                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10577         }
10578
10579         if(!rsurface.lightmapcolor4f)
10580                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
10581
10582         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
10583         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
10584         if(r_refdef.fogenabled)
10585                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
10586
10587         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10588         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10589 }
10590
10591 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10592 {
10593         CHECKGLERROR
10594         RSurf_SetupDepthAndCulling();
10595         if (r_showsurfaces.integer == 3 && !prepass)
10596         {
10597                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10598                 return;
10599         }
10600         switch (vid.renderpath)
10601         {
10602         case RENDERPATH_GL20:
10603         case RENDERPATH_CGGL:
10604                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10605                 break;
10606         case RENDERPATH_GL13:
10607                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10608                 break;
10609         case RENDERPATH_GL11:
10610                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10611                 break;
10612         }
10613         CHECKGLERROR
10614 }
10615
10616 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10617 {
10618         CHECKGLERROR
10619         RSurf_SetupDepthAndCulling();
10620         if (r_showsurfaces.integer == 3 && !prepass)
10621         {
10622                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
10623                 return;
10624         }
10625         switch (vid.renderpath)
10626         {
10627         case RENDERPATH_GL20:
10628         case RENDERPATH_CGGL:
10629                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10630                 break;
10631         case RENDERPATH_GL13:
10632                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10633                 break;
10634         case RENDERPATH_GL11:
10635                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10636                 break;
10637         }
10638         CHECKGLERROR
10639 }
10640
10641 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10642 {
10643         int i, j;
10644         int texturenumsurfaces, endsurface;
10645         texture_t *texture;
10646         const msurface_t *surface;
10647         const msurface_t *texturesurfacelist[256];
10648
10649         // if the model is static it doesn't matter what value we give for
10650         // wantnormals and wanttangents, so this logic uses only rules applicable
10651         // to a model, knowing that they are meaningless otherwise
10652         if (ent == r_refdef.scene.worldentity)
10653                 RSurf_ActiveWorldEntity();
10654         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10655                 RSurf_ActiveModelEntity(ent, false, false, false);
10656         else
10657         {
10658                 switch (vid.renderpath)
10659                 {
10660                 case RENDERPATH_GL20:
10661                 case RENDERPATH_CGGL:
10662                         RSurf_ActiveModelEntity(ent, true, true, false);
10663                         break;
10664                 case RENDERPATH_GL13:
10665                 case RENDERPATH_GL11:
10666                         RSurf_ActiveModelEntity(ent, true, false, false);
10667                         break;
10668                 }
10669         }
10670
10671         if (r_transparentdepthmasking.integer)
10672         {
10673                 qboolean setup = false;
10674                 for (i = 0;i < numsurfaces;i = j)
10675                 {
10676                         j = i + 1;
10677                         surface = rsurface.modelsurfaces + surfacelist[i];
10678                         texture = surface->texture;
10679                         rsurface.texture = R_GetCurrentTexture(texture);
10680                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10681                         // scan ahead until we find a different texture
10682                         endsurface = min(i + 1024, numsurfaces);
10683                         texturenumsurfaces = 0;
10684                         texturesurfacelist[texturenumsurfaces++] = surface;
10685                         for (;j < endsurface;j++)
10686                         {
10687                                 surface = rsurface.modelsurfaces + surfacelist[j];
10688                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10689                                         break;
10690                                 texturesurfacelist[texturenumsurfaces++] = surface;
10691                         }
10692                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10693                                 continue;
10694                         // render the range of surfaces as depth
10695                         if (!setup)
10696                         {
10697                                 setup = true;
10698                                 GL_ColorMask(0,0,0,0);
10699                                 GL_Color(1,1,1,1);
10700                                 GL_DepthTest(true);
10701                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10702                                 GL_DepthMask(true);
10703                                 GL_AlphaTest(false);
10704                                 R_Mesh_ColorPointer(NULL, 0, 0);
10705                                 R_Mesh_ResetTextureState();
10706                                 R_SetupShader_DepthOrShadow();
10707                         }
10708                         RSurf_SetupDepthAndCulling();
10709                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10710                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10711                 }
10712                 if (setup)
10713                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10714         }
10715
10716         for (i = 0;i < numsurfaces;i = j)
10717         {
10718                 j = i + 1;
10719                 surface = rsurface.modelsurfaces + surfacelist[i];
10720                 texture = surface->texture;
10721                 rsurface.texture = R_GetCurrentTexture(texture);
10722                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10723                 // scan ahead until we find a different texture
10724                 endsurface = min(i + 1024, numsurfaces);
10725                 texturenumsurfaces = 0;
10726                 texturesurfacelist[texturenumsurfaces++] = surface;
10727                 for (;j < endsurface;j++)
10728                 {
10729                         surface = rsurface.modelsurfaces + surfacelist[j];
10730                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
10731                                 break;
10732                         texturesurfacelist[texturenumsurfaces++] = surface;
10733                 }
10734                 // render the range of surfaces
10735                 if (ent == r_refdef.scene.worldentity)
10736                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10737                 else
10738                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10739         }
10740         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10741         GL_AlphaTest(false);
10742 }
10743
10744 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10745 {
10746         // transparent surfaces get pushed off into the transparent queue
10747         int surfacelistindex;
10748         const msurface_t *surface;
10749         vec3_t tempcenter, center;
10750         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10751         {
10752                 surface = texturesurfacelist[surfacelistindex];
10753                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10754                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10755                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10756                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10757                 if (queueentity->transparent_offset) // transparent offset
10758                 {
10759                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10760                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10761                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10762                 }
10763                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10764         }
10765 }
10766
10767 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10768 {
10769         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10770         CHECKGLERROR
10771         if (depthonly)
10772         {
10773                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10774                         return;
10775                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10776                         return;
10777                 RSurf_SetupDepthAndCulling();
10778                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10779                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10780         }
10781         else if (prepass)
10782         {
10783                 if (!rsurface.texture->currentnumlayers)
10784                         return;
10785                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10786                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10787                 else
10788                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10789         }
10790         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
10791         {
10792                 RSurf_SetupDepthAndCulling();
10793                 GL_AlphaTest(false);
10794                 R_Mesh_ColorPointer(NULL, 0, 0);
10795                 R_Mesh_ResetTextureState();
10796                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10797                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10798                 GL_DepthMask(true);
10799                 GL_BlendFunc(GL_ONE, GL_ZERO);
10800                 GL_Color(0, 0, 0, 1);
10801                 GL_DepthTest(writedepth);
10802                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10803         }
10804         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
10805         {
10806                 RSurf_SetupDepthAndCulling();
10807                 GL_AlphaTest(false);
10808                 R_Mesh_ColorPointer(NULL, 0, 0);
10809                 R_Mesh_ResetTextureState();
10810                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10811                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10812                 GL_DepthMask(true);
10813                 GL_BlendFunc(GL_ONE, GL_ZERO);
10814                 GL_DepthTest(true);
10815                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10816         }
10817         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10818                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10819         else if (!rsurface.texture->currentnumlayers)
10820                 return;
10821         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10822         {
10823                 // in the deferred case, transparent surfaces were queued during prepass
10824                 if (!r_shadow_usingdeferredprepass)
10825                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10826         }
10827         else
10828         {
10829                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10830                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10831         }
10832         CHECKGLERROR
10833 }
10834
10835 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10836 {
10837         int i, j;
10838         texture_t *texture;
10839         // break the surface list down into batches by texture and use of lightmapping
10840         for (i = 0;i < numsurfaces;i = j)
10841         {
10842                 j = i + 1;
10843                 // texture is the base texture pointer, rsurface.texture is the
10844                 // current frame/skin the texture is directing us to use (for example
10845                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10846                 // use skin 1 instead)
10847                 texture = surfacelist[i]->texture;
10848                 rsurface.texture = R_GetCurrentTexture(texture);
10849                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10850                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10851                 {
10852                         // if this texture is not the kind we want, skip ahead to the next one
10853                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10854                                 ;
10855                         continue;
10856                 }
10857                 // simply scan ahead until we find a different texture or lightmap state
10858                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10859                         ;
10860                 // render the range of surfaces
10861                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10862         }
10863 }
10864
10865 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10866 {
10867         CHECKGLERROR
10868         if (depthonly)
10869         {
10870                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10871                         return;
10872                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10873                         return;
10874                 RSurf_SetupDepthAndCulling();
10875                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10876                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10877         }
10878         else if (prepass)
10879         {
10880                 if (!rsurface.texture->currentnumlayers)
10881                         return;
10882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10883                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10884                 else
10885                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10886         }
10887         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
10888         {
10889                 RSurf_SetupDepthAndCulling();
10890                 GL_AlphaTest(false);
10891                 R_Mesh_ColorPointer(NULL, 0, 0);
10892                 R_Mesh_ResetTextureState();
10893                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10894                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10895                 GL_DepthMask(true);
10896                 GL_BlendFunc(GL_ONE, GL_ZERO);
10897                 GL_Color(0, 0, 0, 1);
10898                 GL_DepthTest(writedepth);
10899                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10900         }
10901         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10902         {
10903                 RSurf_SetupDepthAndCulling();
10904                 GL_AlphaTest(false);
10905                 R_Mesh_ColorPointer(NULL, 0, 0);
10906                 R_Mesh_ResetTextureState();
10907                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10908                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10909                 GL_DepthMask(true);
10910                 GL_BlendFunc(GL_ONE, GL_ZERO);
10911                 GL_DepthTest(true);
10912                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
10913         }
10914         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
10915                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10916         else if (!rsurface.texture->currentnumlayers)
10917                 return;
10918         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10919         {
10920                 // in the deferred case, transparent surfaces were queued during prepass
10921                 if (!r_shadow_usingdeferredprepass)
10922                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10923         }
10924         else
10925         {
10926                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10927                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10928         }
10929         CHECKGLERROR
10930 }
10931
10932 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10933 {
10934         int i, j;
10935         texture_t *texture;
10936         // break the surface list down into batches by texture and use of lightmapping
10937         for (i = 0;i < numsurfaces;i = j)
10938         {
10939                 j = i + 1;
10940                 // texture is the base texture pointer, rsurface.texture is the
10941                 // current frame/skin the texture is directing us to use (for example
10942                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10943                 // use skin 1 instead)
10944                 texture = surfacelist[i]->texture;
10945                 rsurface.texture = R_GetCurrentTexture(texture);
10946                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
10947                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10948                 {
10949                         // if this texture is not the kind we want, skip ahead to the next one
10950                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10951                                 ;
10952                         continue;
10953                 }
10954                 // simply scan ahead until we find a different texture or lightmap state
10955                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
10956                         ;
10957                 // render the range of surfaces
10958                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10959         }
10960 }
10961
10962 float locboxvertex3f[6*4*3] =
10963 {
10964         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10965         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10966         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10967         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10968         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10969         1,0,0, 0,0,0, 0,1,0, 1,1,0
10970 };
10971
10972 unsigned short locboxelements[6*2*3] =
10973 {
10974          0, 1, 2, 0, 2, 3,
10975          4, 5, 6, 4, 6, 7,
10976          8, 9,10, 8,10,11,
10977         12,13,14, 12,14,15,
10978         16,17,18, 16,18,19,
10979         20,21,22, 20,22,23
10980 };
10981
10982 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10983 {
10984         int i, j;
10985         cl_locnode_t *loc = (cl_locnode_t *)ent;
10986         vec3_t mins, size;
10987         float vertex3f[6*4*3];
10988         CHECKGLERROR
10989         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10990         GL_DepthMask(false);
10991         GL_DepthRange(0, 1);
10992         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10993         GL_DepthTest(true);
10994         GL_CullFace(GL_NONE);
10995         R_EntityMatrix(&identitymatrix);
10996
10997         R_Mesh_VertexPointer(vertex3f, 0, 0);
10998         R_Mesh_ColorPointer(NULL, 0, 0);
10999         R_Mesh_ResetTextureState();
11000         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11001
11002         i = surfacelist[0];
11003         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11004                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11005                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11006                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11007
11008         if (VectorCompare(loc->mins, loc->maxs))
11009         {
11010                 VectorSet(size, 2, 2, 2);
11011                 VectorMA(loc->mins, -0.5f, size, mins);
11012         }
11013         else
11014         {
11015                 VectorCopy(loc->mins, mins);
11016                 VectorSubtract(loc->maxs, loc->mins, size);
11017         }
11018
11019         for (i = 0;i < 6*4*3;)
11020                 for (j = 0;j < 3;j++, i++)
11021                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11022
11023         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11024 }
11025
11026 void R_DrawLocs(void)
11027 {
11028         int index;
11029         cl_locnode_t *loc, *nearestloc;
11030         vec3_t center;
11031         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11032         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11033         {
11034                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11035                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11036         }
11037 }
11038
11039 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11040 {
11041         if (decalsystem->decals)
11042                 Mem_Free(decalsystem->decals);
11043         memset(decalsystem, 0, sizeof(*decalsystem));
11044 }
11045
11046 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
11047 {
11048         tridecal_t *decal;
11049         tridecal_t *decals;
11050         int i;
11051         int maxdecals;
11052
11053         // expand or initialize the system
11054         if (decalsystem->maxdecals <= decalsystem->numdecals)
11055         {
11056                 decalsystem_t old = *decalsystem;
11057                 qboolean useshortelements;
11058                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11059                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11060                 decalsystem->decals = Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
11061                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11062                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11063                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11064                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11065                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11066                 if (decalsystem->numdecals)
11067                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11068                 if (old.decals)
11069                         Mem_Free(old.decals);
11070                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11071                         decalsystem->element3i[i] = i;
11072                 if (useshortelements)
11073                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11074                                 decalsystem->element3s[i] = i;
11075         }
11076
11077         // grab a decal and search for another free slot for the next one
11078         maxdecals = decalsystem->maxdecals;
11079         decals = decalsystem->decals;
11080         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11081         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11082                 ;
11083         decalsystem->freedecal = i;
11084         if (decalsystem->numdecals <= i)
11085                 decalsystem->numdecals = i + 1;
11086
11087         // initialize the decal
11088         decal->lived = 0;
11089         decal->triangleindex = triangleindex;
11090         decal->surfaceindex = surfaceindex;
11091         decal->decalsequence = decalsequence;
11092         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11093         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11094         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11095         decal->color4ub[0][3] = 255;
11096         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11097         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11098         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11099         decal->color4ub[1][3] = 255;
11100         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11101         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11102         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11103         decal->color4ub[2][3] = 255;
11104         decal->vertex3f[0][0] = v0[0];
11105         decal->vertex3f[0][1] = v0[1];
11106         decal->vertex3f[0][2] = v0[2];
11107         decal->vertex3f[1][0] = v1[0];
11108         decal->vertex3f[1][1] = v1[1];
11109         decal->vertex3f[1][2] = v1[2];
11110         decal->vertex3f[2][0] = v2[0];
11111         decal->vertex3f[2][1] = v2[1];
11112         decal->vertex3f[2][2] = v2[2];
11113         decal->texcoord2f[0][0] = t0[0];
11114         decal->texcoord2f[0][1] = t0[1];
11115         decal->texcoord2f[1][0] = t1[0];
11116         decal->texcoord2f[1][1] = t1[1];
11117         decal->texcoord2f[2][0] = t2[0];
11118         decal->texcoord2f[2][1] = t2[1];
11119 }
11120
11121 extern cvar_t cl_decals_bias;
11122 extern cvar_t cl_decals_models;
11123 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11124 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11125 {
11126         matrix4x4_t projection;
11127         decalsystem_t *decalsystem;
11128         qboolean dynamic;
11129         dp_model_t *model;
11130         const float *vertex3f;
11131         const msurface_t *surface;
11132         const msurface_t *surfaces;
11133         const int *surfacelist;
11134         const texture_t *texture;
11135         int numvertices;
11136         int numtriangles;
11137         int numsurfacelist;
11138         int surfacelistindex;
11139         int surfaceindex;
11140         int triangleindex;
11141         int decalsurfaceindex;
11142         int cornerindex;
11143         int index;
11144         int numpoints;
11145         const int *e;
11146         float localorigin[3];
11147         float localnormal[3];
11148         float localmins[3];
11149         float localmaxs[3];
11150         float localsize;
11151         float ilocalsize;
11152         float v[9][3];
11153         float tc[9][2];
11154         float c[9][4];
11155         //float normal[3];
11156         float planes[6][4];
11157         float f;
11158         float points[2][9][3];
11159         float angles[3];
11160         float temp[3];
11161
11162         decalsystem = &ent->decalsystem;
11163         model = ent->model;
11164         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11165         {
11166                 R_DecalSystem_Reset(&ent->decalsystem);
11167                 return;
11168         }
11169
11170         if (!model->brush.data_nodes && !cl_decals_models.integer)
11171         {
11172                 if (decalsystem->model)
11173                         R_DecalSystem_Reset(decalsystem);
11174                 return;
11175         }
11176
11177         if (decalsystem->model != model)
11178                 R_DecalSystem_Reset(decalsystem);
11179         decalsystem->model = model;
11180
11181         RSurf_ActiveModelEntity(ent, false, false, false);
11182
11183         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11184         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11185         VectorNormalize(localnormal);
11186         localsize = worldsize*rsurface.inversematrixscale;
11187         ilocalsize = 1.0f / localsize;
11188         localmins[0] = localorigin[0] - localsize;
11189         localmins[1] = localorigin[1] - localsize;
11190         localmins[2] = localorigin[2] - localsize;
11191         localmaxs[0] = localorigin[0] + localsize;
11192         localmaxs[1] = localorigin[1] + localsize;
11193         localmaxs[2] = localorigin[2] + localsize;
11194
11195         //VectorCopy(localnormal, planes[4]);
11196         //VectorVectors(planes[4], planes[2], planes[0]);
11197         AnglesFromVectors(angles, localnormal, NULL, false);
11198         AngleVectors(angles, planes[0], planes[2], planes[4]);
11199         VectorNegate(planes[0], planes[1]);
11200         VectorNegate(planes[2], planes[3]);
11201         VectorNegate(planes[4], planes[5]);
11202         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11203         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11204         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11205         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11206         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11207         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11208
11209 #if 1
11210 // works
11211 {
11212         matrix4x4_t forwardprojection;
11213         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11214         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11215 }
11216 #else
11217 // broken
11218 {
11219         float projectionvector[4][3];
11220         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11221         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11222         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11223         projectionvector[0][0] = planes[0][0] * ilocalsize;
11224         projectionvector[0][1] = planes[1][0] * ilocalsize;
11225         projectionvector[0][2] = planes[2][0] * ilocalsize;
11226         projectionvector[1][0] = planes[0][1] * ilocalsize;
11227         projectionvector[1][1] = planes[1][1] * ilocalsize;
11228         projectionvector[1][2] = planes[2][1] * ilocalsize;
11229         projectionvector[2][0] = planes[0][2] * ilocalsize;
11230         projectionvector[2][1] = planes[1][2] * ilocalsize;
11231         projectionvector[2][2] = planes[2][2] * ilocalsize;
11232         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11233         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11234         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11235         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11236 }
11237 #endif
11238
11239         dynamic = model->surfmesh.isanimated;
11240         vertex3f = rsurface.modelvertex3f;
11241         numsurfacelist = model->nummodelsurfaces;
11242         surfacelist = model->sortedmodelsurfaces;
11243         surfaces = model->data_surfaces;
11244         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11245         {
11246                 surfaceindex = surfacelist[surfacelistindex];
11247                 surface = surfaces + surfaceindex;
11248                 // skip transparent surfaces
11249                 texture = surface->texture;
11250                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11251                         continue;
11252                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11253                         continue;
11254                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11255                         continue;
11256                 decalsurfaceindex = ent == r_refdef.scene.worldentity ? surfaceindex : -1;
11257                 numvertices = surface->num_vertices;
11258                 numtriangles = surface->num_triangles;
11259                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11260                 {
11261                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11262                         {
11263                                 index = 3*e[cornerindex];
11264                                 VectorCopy(vertex3f + index, v[cornerindex]);
11265                         }
11266                         // cull backfaces
11267                         //TriangleNormal(v[0], v[1], v[2], normal);
11268                         //if (DotProduct(normal, localnormal) < 0.0f)
11269                         //      continue;
11270                         // clip by each of the box planes formed from the projection matrix
11271                         // if anything survives, we emit the decal
11272                         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11273                         if (numpoints < 3)
11274                                 continue;
11275                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11276                         if (numpoints < 3)
11277                                 continue;
11278                         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11279                         if (numpoints < 3)
11280                                 continue;
11281                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
11282                         if (numpoints < 3)
11283                                 continue;
11284                         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
11285                         if (numpoints < 3)
11286                                 continue;
11287                         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
11288                         if (numpoints < 3)
11289                                 continue;
11290                         // some part of the triangle survived, so we have to accept it...
11291                         if (dynamic)
11292                         {
11293                                 // dynamic always uses the original triangle
11294                                 numpoints = 3;
11295                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11296                                 {
11297                                         index = 3*e[cornerindex];
11298                                         VectorCopy(vertex3f + index, v[cornerindex]);
11299                                 }
11300                         }
11301                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11302                         {
11303                                 // convert vertex positions to texcoords
11304                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11305                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11306                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11307                                 // calculate distance fade from the projection origin
11308                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11309                                 f = bound(0.0f, f, 1.0f);
11310                                 c[cornerindex][0] = r * f;
11311                                 c[cornerindex][1] = g * f;
11312                                 c[cornerindex][2] = b * f;
11313                                 c[cornerindex][3] = 1.0f;
11314                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11315                         }
11316                         if (dynamic)
11317                                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex+surface->num_firsttriangle, surfaceindex, decalsequence);
11318                         else
11319                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11320                                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
11321                 }
11322         }
11323 }
11324
11325 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11326 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11327 {
11328         int renderentityindex;
11329         float worldmins[3];
11330         float worldmaxs[3];
11331         entity_render_t *ent;
11332
11333         if (!cl_decals_newsystem.integer)
11334                 return;
11335
11336         worldmins[0] = worldorigin[0] - worldsize;
11337         worldmins[1] = worldorigin[1] - worldsize;
11338         worldmins[2] = worldorigin[2] - worldsize;
11339         worldmaxs[0] = worldorigin[0] + worldsize;
11340         worldmaxs[1] = worldorigin[1] + worldsize;
11341         worldmaxs[2] = worldorigin[2] + worldsize;
11342
11343         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11344
11345         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11346         {
11347                 ent = r_refdef.scene.entities[renderentityindex];
11348                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11349                         continue;
11350
11351                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11352         }
11353 }
11354
11355 typedef struct r_decalsystem_splatqueue_s
11356 {
11357         vec3_t worldorigin;
11358         vec3_t worldnormal;
11359         float color[4];
11360         float tcrange[4];
11361         float worldsize;
11362         int decalsequence;
11363 }
11364 r_decalsystem_splatqueue_t;
11365
11366 int r_decalsystem_numqueued = 0;
11367 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11368
11369 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11370 {
11371         r_decalsystem_splatqueue_t *queue;
11372
11373         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11374                 return;
11375
11376         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11377         VectorCopy(worldorigin, queue->worldorigin);
11378         VectorCopy(worldnormal, queue->worldnormal);
11379         Vector4Set(queue->color, r, g, b, a);
11380         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11381         queue->worldsize = worldsize;
11382         queue->decalsequence = cl.decalsequence++;
11383 }
11384
11385 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11386 {
11387         int i;
11388         r_decalsystem_splatqueue_t *queue;
11389
11390         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11391                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11392         r_decalsystem_numqueued = 0;
11393 }
11394
11395 extern cvar_t cl_decals_max;
11396 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11397 {
11398         int i;
11399         decalsystem_t *decalsystem = &ent->decalsystem;
11400         int numdecals;
11401         int killsequence;
11402         tridecal_t *decal;
11403         float frametime;
11404         float lifetime;
11405
11406         if (!decalsystem->numdecals)
11407                 return;
11408
11409         if (r_showsurfaces.integer)
11410                 return;
11411
11412         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11413         {
11414                 R_DecalSystem_Reset(decalsystem);
11415                 return;
11416         }
11417
11418         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11419         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11420
11421         if (decalsystem->lastupdatetime)
11422                 frametime = (cl.time - decalsystem->lastupdatetime);
11423         else
11424                 frametime = 0;
11425         decalsystem->lastupdatetime = cl.time;
11426         decal = decalsystem->decals;
11427         numdecals = decalsystem->numdecals;
11428
11429         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11430         {
11431                 if (decal->color4ub[0][3])
11432                 {
11433                         decal->lived += frametime;
11434                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11435                         {
11436                                 memset(decal, 0, sizeof(*decal));
11437                                 if (decalsystem->freedecal > i)
11438                                         decalsystem->freedecal = i;
11439                         }
11440                 }
11441         }
11442         decal = decalsystem->decals;
11443         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11444                 numdecals--;
11445
11446         // collapse the array by shuffling the tail decals into the gaps
11447         for (;;)
11448         {
11449                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11450                         decalsystem->freedecal++;
11451                 if (decalsystem->freedecal == numdecals)
11452                         break;
11453                 decal[decalsystem->freedecal] = decal[--numdecals];
11454         }
11455
11456         decalsystem->numdecals = numdecals;
11457
11458         if (numdecals <= 0)
11459         {
11460                 // if there are no decals left, reset decalsystem
11461                 R_DecalSystem_Reset(decalsystem);
11462         }
11463 }
11464
11465 extern skinframe_t *decalskinframe;
11466 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11467 {
11468         int i;
11469         decalsystem_t *decalsystem = &ent->decalsystem;
11470         int numdecals;
11471         tridecal_t *decal;
11472         float fadedelay;
11473         float faderate;
11474         float alpha;
11475         float *v3f;
11476         float *c4f;
11477         float *t2f;
11478         const int *e;
11479         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11480         int numtris = 0;
11481
11482         numdecals = decalsystem->numdecals;
11483         if (!numdecals)
11484                 return;
11485
11486         if (r_showsurfaces.integer)
11487                 return;
11488
11489         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11490         {
11491                 R_DecalSystem_Reset(decalsystem);
11492                 return;
11493         }
11494
11495         // if the model is static it doesn't matter what value we give for
11496         // wantnormals and wanttangents, so this logic uses only rules applicable
11497         // to a model, knowing that they are meaningless otherwise
11498         if (ent == r_refdef.scene.worldentity)
11499                 RSurf_ActiveWorldEntity();
11500         else
11501                 RSurf_ActiveModelEntity(ent, false, false, false);
11502
11503         decalsystem->lastupdatetime = cl.time;
11504         decal = decalsystem->decals;
11505
11506         fadedelay = cl_decals_time.value;
11507         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11508
11509         // update vertex positions for animated models
11510         v3f = decalsystem->vertex3f;
11511         c4f = decalsystem->color4f;
11512         t2f = decalsystem->texcoord2f;
11513         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11514         {
11515                 if (!decal->color4ub[0][3])
11516                         continue;
11517
11518                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11519                         continue;
11520
11521                 // update color values for fading decals
11522                 if (decal->lived >= cl_decals_time.value)
11523                 {
11524                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11525                         alpha *= (1.0f/255.0f);
11526                 }
11527                 else
11528                         alpha = 1.0f/255.0f;
11529
11530                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11531                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11532                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11533                 c4f[ 3] = 1;
11534                 c4f[ 4] = decal->color4ub[1][0] * alpha;
11535                 c4f[ 5] = decal->color4ub[1][1] * alpha;
11536                 c4f[ 6] = decal->color4ub[1][2] * alpha;
11537                 c4f[ 7] = 1;
11538                 c4f[ 8] = decal->color4ub[2][0] * alpha;
11539                 c4f[ 9] = decal->color4ub[2][1] * alpha;
11540                 c4f[10] = decal->color4ub[2][2] * alpha;
11541                 c4f[11] = 1;
11542
11543                 t2f[0] = decal->texcoord2f[0][0];
11544                 t2f[1] = decal->texcoord2f[0][1];
11545                 t2f[2] = decal->texcoord2f[1][0];
11546                 t2f[3] = decal->texcoord2f[1][1];
11547                 t2f[4] = decal->texcoord2f[2][0];
11548                 t2f[5] = decal->texcoord2f[2][1];
11549
11550                 // update vertex positions for animated models
11551                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
11552                 {
11553                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11554                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
11555                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
11556                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
11557                 }
11558                 else
11559                 {
11560                         VectorCopy(decal->vertex3f[0], v3f);
11561                         VectorCopy(decal->vertex3f[1], v3f + 3);
11562                         VectorCopy(decal->vertex3f[2], v3f + 6);
11563                 }
11564
11565                 v3f += 9;
11566                 c4f += 12;
11567                 t2f += 6;
11568                 numtris++;
11569         }
11570
11571         if (numtris > 0)
11572         {
11573                 r_refdef.stats.drawndecals += numtris;
11574
11575                 if (r_refdef.fogenabled)
11576                 {
11577                         switch(vid.renderpath)
11578                         {
11579                         case RENDERPATH_GL20:
11580                         case RENDERPATH_CGGL:
11581                         case RENDERPATH_GL13:
11582                         case RENDERPATH_GL11:
11583                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
11584                                 {
11585                                         alpha = RSurf_FogVertex(v3f);
11586                                         c4f[0] *= alpha;
11587                                         c4f[1] *= alpha;
11588                                         c4f[2] *= alpha;
11589                                 }
11590                                 break;
11591                         }
11592                 }
11593
11594                 // now render the decals all at once
11595                 // (this assumes they all use one particle font texture!)
11596                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11597                 R_Mesh_ResetTextureState();
11598                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
11599                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
11600                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
11601                 GL_DepthMask(false);
11602                 GL_DepthRange(0, 1);
11603                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11604                 GL_DepthTest(true);
11605                 GL_CullFace(GL_NONE);
11606                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11607                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
11608                 GL_LockArrays(0, numtris * 3);
11609                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
11610                 GL_LockArrays(0, 0);
11611         }
11612 }
11613
11614 static void R_DrawModelDecals(void)
11615 {
11616         int i, numdecals;
11617
11618         // fade faster when there are too many decals
11619         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11620         for (i = 0;i < r_refdef.scene.numentities;i++)
11621                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11622
11623         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11624         for (i = 0;i < r_refdef.scene.numentities;i++)
11625                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11626                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11627
11628         R_DecalSystem_ApplySplatEntitiesQueue();
11629
11630         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11631         for (i = 0;i < r_refdef.scene.numentities;i++)
11632                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11633
11634         r_refdef.stats.totaldecals += numdecals;
11635
11636         if (r_showsurfaces.integer)
11637                 return;
11638
11639         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11640
11641         for (i = 0;i < r_refdef.scene.numentities;i++)
11642         {
11643                 if (!r_refdef.viewcache.entityvisible[i])
11644                         continue;
11645                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11646                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11647         }
11648 }
11649
11650 void R_DrawDebugModel(void)
11651 {
11652         entity_render_t *ent = rsurface.entity;
11653         int i, j, k, l, flagsmask;
11654         const int *elements;
11655         q3mbrush_t *brush;
11656         const msurface_t *surface;
11657         dp_model_t *model = ent->model;
11658         vec3_t v;
11659
11660         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11661
11662         R_Mesh_ColorPointer(NULL, 0, 0);
11663         R_Mesh_ResetTextureState();
11664         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11665         GL_DepthRange(0, 1);
11666         GL_DepthTest(!r_showdisabledepthtest.integer);
11667         GL_DepthMask(false);
11668         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11669
11670         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
11671         {
11672                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11673                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
11674                 {
11675                         if (brush->colbrushf && brush->colbrushf->numtriangles)
11676                         {
11677                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
11678                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11679                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
11680                         }
11681                 }
11682                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
11683                 {
11684                         if (surface->num_collisiontriangles)
11685                         {
11686                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
11687                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11688                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
11689                         }
11690                 }
11691         }
11692
11693         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11694
11695         if (r_showtris.integer || r_shownormals.integer)
11696         {
11697                 if (r_showdisabledepthtest.integer)
11698                 {
11699                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11700                         GL_DepthMask(false);
11701                 }
11702                 else
11703                 {
11704                         GL_BlendFunc(GL_ONE, GL_ZERO);
11705                         GL_DepthMask(true);
11706                 }
11707                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11708                 {
11709                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11710                                 continue;
11711                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11712                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11713                         {
11714                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
11715                                 if (r_showtris.value > 0)
11716                                 {
11717                                         if (!rsurface.texture->currentlayers->depthmask)
11718                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11719                                         else if (ent == r_refdef.scene.worldentity)
11720                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11721                                         else
11722                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11723                                         elements = (model->surfmesh.data_element3i + 3 * surface->num_firsttriangle);
11724                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
11725                                         R_Mesh_ColorPointer(NULL, 0, 0);
11726                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
11727                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11728                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
11729                                         R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
11730                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11731                                         CHECKGLERROR
11732                                 }
11733                                 if (r_shownormals.value < 0)
11734                                 {
11735                                         qglBegin(GL_LINES);
11736                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11737                                         {
11738                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11739                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11740                                                 qglVertex3f(v[0], v[1], v[2]);
11741                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
11742                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11743                                                 qglVertex3f(v[0], v[1], v[2]);
11744                                         }
11745                                         qglEnd();
11746                                         CHECKGLERROR
11747                                 }
11748                                 if (r_shownormals.value > 0)
11749                                 {
11750                                         qglBegin(GL_LINES);
11751                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11752                                         {
11753                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11754                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11755                                                 qglVertex3f(v[0], v[1], v[2]);
11756                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
11757                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11758                                                 qglVertex3f(v[0], v[1], v[2]);
11759                                         }
11760                                         qglEnd();
11761                                         CHECKGLERROR
11762                                         qglBegin(GL_LINES);
11763                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11764                                         {
11765                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11766                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11767                                                 qglVertex3f(v[0], v[1], v[2]);
11768                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
11769                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11770                                                 qglVertex3f(v[0], v[1], v[2]);
11771                                         }
11772                                         qglEnd();
11773                                         CHECKGLERROR
11774                                         qglBegin(GL_LINES);
11775                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
11776                                         {
11777                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
11778                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11779                                                 qglVertex3f(v[0], v[1], v[2]);
11780                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
11781                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
11782                                                 qglVertex3f(v[0], v[1], v[2]);
11783                                         }
11784                                         qglEnd();
11785                                         CHECKGLERROR
11786                                 }
11787                         }
11788                 }
11789                 rsurface.texture = NULL;
11790         }
11791 }
11792
11793 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11794 int r_maxsurfacelist = 0;
11795 const msurface_t **r_surfacelist = NULL;
11796 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11797 {
11798         int i, j, endj, f, flagsmask;
11799         texture_t *t;
11800         dp_model_t *model = r_refdef.scene.worldmodel;
11801         msurface_t *surfaces;
11802         unsigned char *update;
11803         int numsurfacelist = 0;
11804         if (model == NULL)
11805                 return;
11806
11807         if (r_maxsurfacelist < model->num_surfaces)
11808         {
11809                 r_maxsurfacelist = model->num_surfaces;
11810                 if (r_surfacelist)
11811                         Mem_Free((msurface_t**)r_surfacelist);
11812                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11813         }
11814
11815         RSurf_ActiveWorldEntity();
11816
11817         surfaces = model->data_surfaces;
11818         update = model->brushq1.lightmapupdateflags;
11819
11820         // update light styles on this submodel
11821         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11822         {
11823                 model_brush_lightstyleinfo_t *style;
11824                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11825                 {
11826                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11827                         {
11828                                 int *list = style->surfacelist;
11829                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11830                                 for (j = 0;j < style->numsurfaces;j++)
11831                                         update[list[j]] = true;
11832                         }
11833                 }
11834         }
11835
11836         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11837
11838         if (debug)
11839         {
11840                 R_DrawDebugModel();
11841                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11842                 return;
11843         }
11844
11845         f = 0;
11846         t = NULL;
11847         rsurface.uselightmaptexture = false;
11848         rsurface.texture = NULL;
11849         rsurface.rtlight = NULL;
11850         numsurfacelist = 0;
11851         // add visible surfaces to draw list
11852         for (i = 0;i < model->nummodelsurfaces;i++)
11853         {
11854                 j = model->sortedmodelsurfaces[i];
11855                 if (r_refdef.viewcache.world_surfacevisible[j])
11856                         r_surfacelist[numsurfacelist++] = surfaces + j;
11857         }
11858         // update lightmaps if needed
11859         if (model->brushq1.firstrender)
11860         {
11861                 model->brushq1.firstrender = false;
11862                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11863                         if (update[j])
11864                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11865         }
11866         else if (update)
11867         {
11868                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11869                         if (r_refdef.viewcache.world_surfacevisible[j])
11870                                 if (update[j])
11871                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11872         }
11873         // don't do anything if there were no surfaces
11874         if (!numsurfacelist)
11875         {
11876                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11877                 return;
11878         }
11879         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11880         GL_AlphaTest(false);
11881
11882         // add to stats if desired
11883         if (r_speeds.integer && !skysurfaces && !depthonly)
11884         {
11885                 r_refdef.stats.world_surfaces += numsurfacelist;
11886                 for (j = 0;j < numsurfacelist;j++)
11887                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11888         }
11889
11890         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11891 }
11892
11893 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11894 {
11895         int i, j, endj, f, flagsmask;
11896         texture_t *t;
11897         dp_model_t *model = ent->model;
11898         msurface_t *surfaces;
11899         unsigned char *update;
11900         int numsurfacelist = 0;
11901         if (model == NULL)
11902                 return;
11903
11904         if (r_maxsurfacelist < model->num_surfaces)
11905         {
11906                 r_maxsurfacelist = model->num_surfaces;
11907                 if (r_surfacelist)
11908                         Mem_Free((msurface_t **)r_surfacelist);
11909                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11910         }
11911
11912         // if the model is static it doesn't matter what value we give for
11913         // wantnormals and wanttangents, so this logic uses only rules applicable
11914         // to a model, knowing that they are meaningless otherwise
11915         if (ent == r_refdef.scene.worldentity)
11916                 RSurf_ActiveWorldEntity();
11917         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11918                 RSurf_ActiveModelEntity(ent, false, false, false);
11919         else if (prepass)
11920                 RSurf_ActiveModelEntity(ent, true, true, true);
11921         else if (depthonly)
11922                 RSurf_ActiveModelEntity(ent, false, false, false);
11923         else
11924         {
11925                 switch (vid.renderpath)
11926                 {
11927                 case RENDERPATH_GL20:
11928                 case RENDERPATH_CGGL:
11929                         RSurf_ActiveModelEntity(ent, true, true, false);
11930                         break;
11931                 case RENDERPATH_GL13:
11932                 case RENDERPATH_GL11:
11933                         RSurf_ActiveModelEntity(ent, true, false, false);
11934                         break;
11935                 }
11936         }
11937
11938         surfaces = model->data_surfaces;
11939         update = model->brushq1.lightmapupdateflags;
11940
11941         // update light styles
11942         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11943         {
11944                 model_brush_lightstyleinfo_t *style;
11945                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11946                 {
11947                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11948                         {
11949                                 int *list = style->surfacelist;
11950                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11951                                 for (j = 0;j < style->numsurfaces;j++)
11952                                         update[list[j]] = true;
11953                         }
11954                 }
11955         }
11956
11957         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11958
11959         if (debug)
11960         {
11961                 R_DrawDebugModel();
11962                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11963                 return;
11964         }
11965
11966         f = 0;
11967         t = NULL;
11968         rsurface.uselightmaptexture = false;
11969         rsurface.texture = NULL;
11970         rsurface.rtlight = NULL;
11971         numsurfacelist = 0;
11972         // add visible surfaces to draw list
11973         for (i = 0;i < model->nummodelsurfaces;i++)
11974                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11975         // don't do anything if there were no surfaces
11976         if (!numsurfacelist)
11977         {
11978                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11979                 return;
11980         }
11981         // update lightmaps if needed
11982         if (update)
11983         {
11984                 int updated = 0;
11985                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11986                 {
11987                         if (update[j])
11988                         {
11989                                 updated++;
11990                                 R_BuildLightMap(ent, surfaces + j);
11991                         }
11992                 }
11993         }
11994         if (update)
11995                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11996                         if (update[j])
11997                                 R_BuildLightMap(ent, surfaces + j);
11998         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11999         GL_AlphaTest(false);
12000
12001         // add to stats if desired
12002         if (r_speeds.integer && !skysurfaces && !depthonly)
12003         {
12004                 r_refdef.stats.entities_surfaces += numsurfacelist;
12005                 for (j = 0;j < numsurfacelist;j++)
12006                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12007         }
12008
12009         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12010 }
12011
12012 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12013 {
12014         static texture_t texture;
12015         static msurface_t surface;
12016         const msurface_t *surfacelist = &surface;
12017
12018         // fake enough texture and surface state to render this geometry
12019
12020         texture.update_lastrenderframe = -1; // regenerate this texture
12021         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12022         texture.currentskinframe = skinframe;
12023         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12024         texture.specularscalemod = 1;
12025         texture.specularpowermod = 1;
12026
12027         surface.texture = &texture;
12028         surface.num_triangles = numtriangles;
12029         surface.num_firsttriangle = firsttriangle;
12030         surface.num_vertices = numvertices;
12031         surface.num_firstvertex = firstvertex;
12032
12033         // now render it
12034         rsurface.texture = R_GetCurrentTexture(surface.texture);
12035         rsurface.uselightmaptexture = false;
12036         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12037 }
12038
12039 void R_DrawCustomSurface_Texture(texture_t *texture, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12040 {
12041         static msurface_t surface;
12042         const msurface_t *surfacelist = &surface;
12043
12044         // fake enough texture and surface state to render this geometry
12045
12046         surface.texture = texture;
12047         surface.num_triangles = numtriangles;
12048         surface.num_firsttriangle = firsttriangle;
12049         surface.num_vertices = numvertices;
12050         surface.num_firstvertex = firstvertex;
12051
12052         // now render it
12053         rsurface.texture = R_GetCurrentTexture(surface.texture);
12054         rsurface.uselightmaptexture = false;
12055         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12056 }