]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
Merge branch 'master' into blub/shader-toys
[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_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
95 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
96 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
97 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"};
98 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"};
99 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
101 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
102 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
103 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"};
104
105 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
106 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
107 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
108 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
109 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
110 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
111 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
112 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
113
114 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)"};
115 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"};
116
117 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
122
123 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
124 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
125 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
126
127 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)"};
128 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
129 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
130 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
131 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
132 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)"};
133 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)"};
134 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)"};
135 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)"};
136
137 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)"};
138 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
139 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"};
140 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
141 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
142
143 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
144 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
145 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
146 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
147
148 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
149 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
150 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
151 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
152 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
153 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
154 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
155
156 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
157 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
158 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
159 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)"};
160
161 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"};
162
163 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"};
164
165 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
166
167 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
168 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
169 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"};
170 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
171 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
172 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
173 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
174 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "16", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
175
176 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
177
178 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)"};
179
180 extern cvar_t v_glslgamma;
181
182 extern qboolean v_flipped_state;
183
184 static struct r_bloomstate_s
185 {
186         qboolean enabled;
187         qboolean hdr;
188
189         int bloomwidth, bloomheight;
190
191         int screentexturewidth, screentextureheight;
192         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
193
194         int bloomtexturewidth, bloomtextureheight;
195         rtexture_t *texture_bloom;
196
197         // arrays for rendering the screen passes
198         float screentexcoord2f[8];
199         float bloomtexcoord2f[8];
200         float offsettexcoord2f[8];
201
202         r_viewport_t viewport;
203 }
204 r_bloomstate;
205
206 r_waterstate_t r_waterstate;
207
208 /// shadow volume bsp struct with automatically growing nodes buffer
209 svbsp_t r_svbsp;
210
211 rtexture_t *r_texture_blanknormalmap;
212 rtexture_t *r_texture_white;
213 rtexture_t *r_texture_grey128;
214 rtexture_t *r_texture_black;
215 rtexture_t *r_texture_notexture;
216 rtexture_t *r_texture_whitecube;
217 rtexture_t *r_texture_normalizationcube;
218 rtexture_t *r_texture_fogattenuation;
219 rtexture_t *r_texture_gammaramps;
220 unsigned int r_texture_gammaramps_serial;
221 //rtexture_t *r_texture_fogintensity;
222 rtexture_t *r_texture_reflectcube;
223
224 // TODO: hash lookups?
225 typedef struct cubemapinfo_s
226 {
227         char basename[64];
228         rtexture_t *texture;
229 }
230 cubemapinfo_t;
231
232 int r_texture_numcubemaps;
233 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
234
235 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
236 unsigned int r_numqueries;
237 unsigned int r_maxqueries;
238
239 typedef struct r_qwskincache_s
240 {
241         char name[MAX_QPATH];
242         skinframe_t *skinframe;
243 }
244 r_qwskincache_t;
245
246 static r_qwskincache_t *r_qwskincache;
247 static int r_qwskincache_size;
248
249 /// vertex coordinates for a quad that covers the screen exactly
250 const float r_screenvertex3f[12] =
251 {
252         0, 0, 0,
253         1, 0, 0,
254         1, 1, 0,
255         0, 1, 0
256 };
257
258 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
259 {
260         int i;
261         for (i = 0;i < verts;i++)
262         {
263                 out[0] = in[0] * r;
264                 out[1] = in[1] * g;
265                 out[2] = in[2] * b;
266                 out[3] = in[3];
267                 in += 4;
268                 out += 4;
269         }
270 }
271
272 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
273 {
274         int i;
275         for (i = 0;i < verts;i++)
276         {
277                 out[0] = r;
278                 out[1] = g;
279                 out[2] = b;
280                 out[3] = a;
281                 out += 4;
282         }
283 }
284
285 // FIXME: move this to client?
286 void FOG_clear(void)
287 {
288         if (gamemode == GAME_NEHAHRA)
289         {
290                 Cvar_Set("gl_fogenable", "0");
291                 Cvar_Set("gl_fogdensity", "0.2");
292                 Cvar_Set("gl_fogred", "0.3");
293                 Cvar_Set("gl_foggreen", "0.3");
294                 Cvar_Set("gl_fogblue", "0.3");
295         }
296         r_refdef.fog_density = 0;
297         r_refdef.fog_red = 0;
298         r_refdef.fog_green = 0;
299         r_refdef.fog_blue = 0;
300         r_refdef.fog_alpha = 1;
301         r_refdef.fog_start = 0;
302         r_refdef.fog_end = 16384;
303         r_refdef.fog_height = 1<<30;
304         r_refdef.fog_fadedepth = 128;
305 }
306
307 static void R_BuildBlankTextures(void)
308 {
309         unsigned char data[4];
310         data[2] = 128; // normal X
311         data[1] = 128; // normal Y
312         data[0] = 255; // normal Z
313         data[3] = 128; // height
314         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
315         data[0] = 255;
316         data[1] = 255;
317         data[2] = 255;
318         data[3] = 255;
319         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
320         data[0] = 128;
321         data[1] = 128;
322         data[2] = 128;
323         data[3] = 255;
324         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
325         data[0] = 0;
326         data[1] = 0;
327         data[2] = 0;
328         data[3] = 255;
329         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
330 }
331
332 static void R_BuildNoTexture(void)
333 {
334         int x, y;
335         unsigned char pix[16][16][4];
336         // this makes a light grey/dark grey checkerboard texture
337         for (y = 0;y < 16;y++)
338         {
339                 for (x = 0;x < 16;x++)
340                 {
341                         if ((y < 8) ^ (x < 8))
342                         {
343                                 pix[y][x][0] = 128;
344                                 pix[y][x][1] = 128;
345                                 pix[y][x][2] = 128;
346                                 pix[y][x][3] = 255;
347                         }
348                         else
349                         {
350                                 pix[y][x][0] = 64;
351                                 pix[y][x][1] = 64;
352                                 pix[y][x][2] = 64;
353                                 pix[y][x][3] = 255;
354                         }
355                 }
356         }
357         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
358 }
359
360 static void R_BuildWhiteCube(void)
361 {
362         unsigned char data[6*1*1*4];
363         memset(data, 255, sizeof(data));
364         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
365 }
366
367 static void R_BuildNormalizationCube(void)
368 {
369         int x, y, side;
370         vec3_t v;
371         vec_t s, t, intensity;
372 #define NORMSIZE 64
373         unsigned char *data;
374         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
375         for (side = 0;side < 6;side++)
376         {
377                 for (y = 0;y < NORMSIZE;y++)
378                 {
379                         for (x = 0;x < NORMSIZE;x++)
380                         {
381                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
383                                 switch(side)
384                                 {
385                                 default:
386                                 case 0:
387                                         v[0] = 1;
388                                         v[1] = -t;
389                                         v[2] = -s;
390                                         break;
391                                 case 1:
392                                         v[0] = -1;
393                                         v[1] = -t;
394                                         v[2] = s;
395                                         break;
396                                 case 2:
397                                         v[0] = s;
398                                         v[1] = 1;
399                                         v[2] = t;
400                                         break;
401                                 case 3:
402                                         v[0] = s;
403                                         v[1] = -1;
404                                         v[2] = -t;
405                                         break;
406                                 case 4:
407                                         v[0] = s;
408                                         v[1] = -t;
409                                         v[2] = 1;
410                                         break;
411                                 case 5:
412                                         v[0] = -s;
413                                         v[1] = -t;
414                                         v[2] = -1;
415                                         break;
416                                 }
417                                 intensity = 127.0f / sqrt(DotProduct(v, v));
418                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
419                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
420                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
421                                 data[((side*64+y)*64+x)*4+3] = 255;
422                         }
423                 }
424         }
425         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
426         Mem_Free(data);
427 }
428
429 static void R_BuildFogTexture(void)
430 {
431         int x, b;
432 #define FOGWIDTH 256
433         unsigned char data1[FOGWIDTH][4];
434         //unsigned char data2[FOGWIDTH][4];
435         double d, r, alpha;
436
437         r_refdef.fogmasktable_start = r_refdef.fog_start;
438         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
439         r_refdef.fogmasktable_range = r_refdef.fogrange;
440         r_refdef.fogmasktable_density = r_refdef.fog_density;
441
442         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
443         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
444         {
445                 d = (x * r - r_refdef.fogmasktable_start);
446                 if(developer_extra.integer)
447                         Con_DPrintf("%f ", d);
448                 d = max(0, d);
449                 if (r_fog_exp2.integer)
450                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
451                 else
452                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
453                 if(developer_extra.integer)
454                         Con_DPrintf(" : %f ", alpha);
455                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
456                 if(developer_extra.integer)
457                         Con_DPrintf(" = %f\n", alpha);
458                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
459         }
460
461         for (x = 0;x < FOGWIDTH;x++)
462         {
463                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
464                 data1[x][0] = b;
465                 data1[x][1] = b;
466                 data1[x][2] = b;
467                 data1[x][3] = 255;
468                 //data2[x][0] = 255 - b;
469                 //data2[x][1] = 255 - b;
470                 //data2[x][2] = 255 - b;
471                 //data2[x][3] = 255;
472         }
473         if (r_texture_fogattenuation)
474         {
475                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
476                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
477         }
478         else
479         {
480                 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);
481                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
482         }
483 }
484
485 //=======================================================================================================================================================
486
487 static const char *builtinshaderstring =
488 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
489 "// written by Forest 'LordHavoc' Hale\n"
490 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
491 "\n"
492 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
493 "# define USEFOG\n"
494 "#endif\n"
495 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
496 "#define USELIGHTMAP\n"
497 "#endif\n"
498 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
499 "#define USEEYEVECTOR\n"
500 "#endif\n"
501 "\n"
502 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
503 "# extension GL_ARB_texture_rectangle : enable\n"
504 "#endif\n"
505 "\n"
506 "#ifdef USESHADOWMAP2D\n"
507 "# ifdef GL_EXT_gpu_shader4\n"
508 "#   extension GL_EXT_gpu_shader4 : enable\n"
509 "# endif\n"
510 "# ifdef GL_ARB_texture_gather\n"
511 "#   extension GL_ARB_texture_gather : enable\n"
512 "# else\n"
513 "#   ifdef GL_AMD_texture_texture4\n"
514 "#     extension GL_AMD_texture_texture4 : enable\n"
515 "#   endif\n"
516 "# endif\n"
517 "#endif\n"
518 "\n"
519 "#ifdef USESHADOWMAPCUBE\n"
520 "# extension GL_EXT_gpu_shader4 : enable\n"
521 "#endif\n"
522 "\n"
523 "//#ifdef USESHADOWSAMPLER\n"
524 "//# extension GL_ARB_shadow : enable\n"
525 "//#endif\n"
526 "\n"
527 "//#ifdef __GLSL_CG_DATA_TYPES\n"
528 "//# define myhalf half\n"
529 "//# define myhalf2 half2\n"
530 "//# define myhalf3 half3\n"
531 "//# define myhalf4 half4\n"
532 "//#else\n"
533 "# define myhalf float\n"
534 "# define myhalf2 vec2\n"
535 "# define myhalf3 vec3\n"
536 "# define myhalf4 vec4\n"
537 "//#endif\n"
538 "\n"
539 "#ifdef VERTEX_SHADER\n"
540 "uniform mat4 ModelViewProjectionMatrix;\n"
541 "#endif\n"
542 "\n"
543 "#ifdef MODE_DEPTH_OR_SHADOW\n"
544 "#ifdef VERTEX_SHADER\n"
545 "void main(void)\n"
546 "{\n"
547 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
548 "}\n"
549 "#endif\n"
550 "#else // !MODE_DEPTH_ORSHADOW\n"
551 "\n"
552 "\n"
553 "\n"
554 "\n"
555 "#ifdef MODE_SHOWDEPTH\n"
556 "#ifdef VERTEX_SHADER\n"
557 "void main(void)\n"
558 "{\n"
559 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
560 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
561 "}\n"
562 "#endif\n"
563 "\n"
564 "#ifdef FRAGMENT_SHADER\n"
565 "void main(void)\n"
566 "{\n"
567 "       gl_FragColor = gl_Color;\n"
568 "}\n"
569 "#endif\n"
570 "#else // !MODE_SHOWDEPTH\n"
571 "\n"
572 "\n"
573 "\n"
574 "\n"
575 "#ifdef MODE_POSTPROCESS\n"
576 "varying vec2 TexCoord1;\n"
577 "varying vec2 TexCoord2;\n"
578 "\n"
579 "#ifdef VERTEX_SHADER\n"
580 "void main(void)\n"
581 "{\n"
582 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
583 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
584 "#ifdef USEBLOOM\n"
585 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
586 "#endif\n"
587 "}\n"
588 "#endif\n"
589 "\n"
590 "#ifdef FRAGMENT_SHADER\n"
591 "uniform sampler2D Texture_First;\n"
592 "#ifdef USEBLOOM\n"
593 "uniform sampler2D Texture_Second;\n"
594 "#endif\n"
595 "#ifdef USEGAMMARAMPS\n"
596 "uniform sampler2D Texture_GammaRamps;\n"
597 "#endif\n"
598 "#ifdef USESATURATION\n"
599 "uniform float Saturation;\n"
600 "#endif\n"
601 "#ifdef USEVIEWTINT\n"
602 "uniform vec4 ViewTintColor;\n"
603 "#endif\n"
604 "//uncomment these if you want to use them:\n"
605 "uniform vec4 UserVec1;\n"
606 "uniform vec4 UserVec2;\n"
607 "// uniform vec4 UserVec3;\n"
608 "// uniform vec4 UserVec4;\n"
609 "// uniform float ClientTime;\n"
610 "uniform vec2 PixelSize;\n"
611 "void main(void)\n"
612 "{\n"
613 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
614 "#ifdef USEBLOOM\n"
615 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
616 "#endif\n"
617 "#ifdef USEVIEWTINT\n"
618 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
619 "#endif\n"
620 "\n"
621 "#ifdef USEPOSTPROCESSING\n"
622 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
623 "// 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"
624 "       float sobel = 1.0;\n"
625 "       // vec2 ts = textureSize(Texture_First, 0);\n"
626 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
627 "       vec2 px = PixelSize;\n"
628 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
629 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
630 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
631 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
632 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
633 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
634 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
635 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
636 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
637 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
638 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
639 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
640 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
641 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
642 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
643 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
644 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
645 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
646 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
647 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
648 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
649 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
650 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
651 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
652 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
653 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
654 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
655 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
656 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
657 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
658 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
659 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
660 "#endif\n"
661 "\n"
662 "#ifdef USESATURATION\n"
663 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
664 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
665 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
666 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
667 "#endif\n"
668 "\n"
669 "#ifdef USEGAMMARAMPS\n"
670 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
671 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
672 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
673 "#endif\n"
674 "}\n"
675 "#endif\n"
676 "#else // !MODE_POSTPROCESS\n"
677 "\n"
678 "\n"
679 "\n"
680 "\n"
681 "#ifdef MODE_GENERIC\n"
682 "#ifdef USEDIFFUSE\n"
683 "varying vec2 TexCoord1;\n"
684 "#endif\n"
685 "#ifdef USESPECULAR\n"
686 "varying vec2 TexCoord2;\n"
687 "#endif\n"
688 "#ifdef VERTEX_SHADER\n"
689 "void main(void)\n"
690 "{\n"
691 "       gl_FrontColor = gl_Color;\n"
692 "#ifdef USEDIFFUSE\n"
693 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
694 "#endif\n"
695 "#ifdef USESPECULAR\n"
696 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
697 "#endif\n"
698 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
699 "}\n"
700 "#endif\n"
701 "\n"
702 "#ifdef FRAGMENT_SHADER\n"
703 "#ifdef USEDIFFUSE\n"
704 "uniform sampler2D Texture_First;\n"
705 "#endif\n"
706 "#ifdef USESPECULAR\n"
707 "uniform sampler2D Texture_Second;\n"
708 "#endif\n"
709 "\n"
710 "void main(void)\n"
711 "{\n"
712 "       gl_FragColor = gl_Color;\n"
713 "#ifdef USEDIFFUSE\n"
714 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
715 "#endif\n"
716 "\n"
717 "#ifdef USESPECULAR\n"
718 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
719 "# ifdef USECOLORMAPPING\n"
720 "       gl_FragColor *= tex2;\n"
721 "# endif\n"
722 "# ifdef USEGLOW\n"
723 "       gl_FragColor += tex2;\n"
724 "# endif\n"
725 "# ifdef USEVERTEXTEXTUREBLEND\n"
726 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
727 "# endif\n"
728 "#endif\n"
729 "}\n"
730 "#endif\n"
731 "#else // !MODE_GENERIC\n"
732 "\n"
733 "\n"
734 "\n"
735 "\n"
736 "#ifdef MODE_BLOOMBLUR\n"
737 "varying TexCoord;\n"
738 "#ifdef VERTEX_SHADER\n"
739 "void main(void)\n"
740 "{\n"
741 "       gl_FrontColor = gl_Color;\n"
742 "       TexCoord = gl_MultiTexCoord0.xy;\n"
743 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
744 "}\n"
745 "#endif\n"
746 "\n"
747 "#ifdef FRAGMENT_SHADER\n"
748 "uniform sampler2D Texture_First;\n"
749 "uniform vec4 BloomBlur_Parameters;\n"
750 "\n"
751 "void main(void)\n"
752 "{\n"
753 "       int i;\n"
754 "       vec2 tc = TexCoord;\n"
755 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
756 "       tc += BloomBlur_Parameters.xy;\n"
757 "       for (i = 1;i < SAMPLES;i++)\n"
758 "       {\n"
759 "               color += texture2D(Texture_First, tc).rgb;\n"
760 "               tc += BloomBlur_Parameters.xy;\n"
761 "       }\n"
762 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_BLOOMBLUR\n"
766 "#ifdef MODE_REFRACTION\n"
767 "varying vec2 TexCoord;\n"
768 "varying vec4 ModelViewProjectionPosition;\n"
769 "uniform mat4 TexMatrix;\n"
770 "#ifdef VERTEX_SHADER\n"
771 "\n"
772 "void main(void)\n"
773 "{\n"
774 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
775 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
776 "       ModelViewProjectionPosition = gl_Position;\n"
777 "}\n"
778 "#endif\n"
779 "\n"
780 "#ifdef FRAGMENT_SHADER\n"
781 "uniform sampler2D Texture_Normal;\n"
782 "uniform sampler2D Texture_Refraction;\n"
783 "uniform sampler2D Texture_Reflection;\n"
784 "\n"
785 "uniform vec4 DistortScaleRefractReflect;\n"
786 "uniform vec4 ScreenScaleRefractReflect;\n"
787 "uniform vec4 ScreenCenterRefractReflect;\n"
788 "uniform vec4 RefractColor;\n"
789 "uniform vec4 ReflectColor;\n"
790 "uniform float ReflectFactor;\n"
791 "uniform float ReflectOffset;\n"
792 "\n"
793 "void main(void)\n"
794 "{\n"
795 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
796 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
797 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
798 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
799 "       // FIXME temporary hack to detect the case that the reflection\n"
800 "       // gets blackened at edges due to leaving the area that contains actual\n"
801 "       // content.\n"
802 "       // Remove this 'ack once we have a better way to stop this thing from\n"
803 "       // 'appening.\n"
804 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
805 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
806 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
807 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
808 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
809 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_REFRACTION\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_WATER\n"
818 "varying vec2 TexCoord;\n"
819 "varying vec3 EyeVector;\n"
820 "varying vec4 ModelViewProjectionPosition;\n"
821 "#ifdef VERTEX_SHADER\n"
822 "uniform vec3 EyePosition;\n"
823 "uniform mat4 TexMatrix;\n"
824 "\n"
825 "void main(void)\n"
826 "{\n"
827 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
828 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
829 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
830 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
831 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "       ModelViewProjectionPosition = gl_Position;\n"
834 "}\n"
835 "#endif\n"
836 "\n"
837 "#ifdef FRAGMENT_SHADER\n"
838 "uniform sampler2D Texture_Normal;\n"
839 "uniform sampler2D Texture_Refraction;\n"
840 "uniform sampler2D Texture_Reflection;\n"
841 "\n"
842 "uniform vec4 DistortScaleRefractReflect;\n"
843 "uniform vec4 ScreenScaleRefractReflect;\n"
844 "uniform vec4 ScreenCenterRefractReflect;\n"
845 "uniform vec4 RefractColor;\n"
846 "uniform vec4 ReflectColor;\n"
847 "uniform float ReflectFactor;\n"
848 "uniform float ReflectOffset;\n"
849 "\n"
850 "void main(void)\n"
851 "{\n"
852 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
853 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
854 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
855 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
856 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
857 "       // FIXME temporary hack to detect the case that the reflection\n"
858 "       // gets blackened at edges due to leaving the area that contains actual\n"
859 "       // content.\n"
860 "       // Remove this 'ack once we have a better way to stop this thing from\n"
861 "       // 'appening.\n"
862 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
863 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
864 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
865 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
866 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
867 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
868 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
869 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
870 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
871 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
872 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
873 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
874 "}\n"
875 "#endif\n"
876 "#else // !MODE_WATER\n"
877 "\n"
878 "\n"
879 "\n"
880 "\n"
881 "// common definitions between vertex shader and fragment shader:\n"
882 "\n"
883 "varying vec2 TexCoord;\n"
884 "#ifdef USEVERTEXTEXTUREBLEND\n"
885 "varying vec2 TexCoord2;\n"
886 "#endif\n"
887 "#ifdef USELIGHTMAP\n"
888 "varying vec2 TexCoordLightmap;\n"
889 "#endif\n"
890 "\n"
891 "#ifdef MODE_LIGHTSOURCE\n"
892 "varying vec3 CubeVector;\n"
893 "#endif\n"
894 "\n"
895 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
896 "varying vec3 LightVector;\n"
897 "#endif\n"
898 "\n"
899 "#ifdef USEEYEVECTOR\n"
900 "varying vec3 EyeVector;\n"
901 "#endif\n"
902 "#ifdef USEFOG\n"
903 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
904 "#endif\n"
905 "\n"
906 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
907 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
908 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
909 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
910 "#endif\n"
911 "\n"
912 "#ifdef USEREFLECTION\n"
913 "varying vec4 ModelViewProjectionPosition;\n"
914 "#endif\n"
915 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
916 "uniform vec3 LightPosition;\n"
917 "varying vec4 ModelViewPosition;\n"
918 "#endif\n"
919 "\n"
920 "#ifdef MODE_LIGHTSOURCE\n"
921 "uniform vec3 LightPosition;\n"
922 "#endif\n"
923 "uniform vec3 EyePosition;\n"
924 "#ifdef MODE_LIGHTDIRECTION\n"
925 "uniform vec3 LightDir;\n"
926 "#endif\n"
927 "uniform vec4 FogPlane;\n"
928 "\n"
929 "#ifdef USESHADOWMAPORTHO\n"
930 "varying vec3 ShadowMapTC;\n"
931 "#endif\n"
932 "\n"
933 "\n"
934 "\n"
935 "\n"
936 "\n"
937 "// 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"
938 "\n"
939 "// fragment shader specific:\n"
940 "#ifdef FRAGMENT_SHADER\n"
941 "\n"
942 "uniform sampler2D Texture_Normal;\n"
943 "uniform sampler2D Texture_Color;\n"
944 "uniform sampler2D Texture_Gloss;\n"
945 "#ifdef USEGLOW\n"
946 "uniform sampler2D Texture_Glow;\n"
947 "#endif\n"
948 "#ifdef USEVERTEXTEXTUREBLEND\n"
949 "uniform sampler2D Texture_SecondaryNormal;\n"
950 "uniform sampler2D Texture_SecondaryColor;\n"
951 "uniform sampler2D Texture_SecondaryGloss;\n"
952 "#ifdef USEGLOW\n"
953 "uniform sampler2D Texture_SecondaryGlow;\n"
954 "#endif\n"
955 "#endif\n"
956 "#ifdef USECOLORMAPPING\n"
957 "uniform sampler2D Texture_Pants;\n"
958 "uniform sampler2D Texture_Shirt;\n"
959 "#endif\n"
960 "#ifdef USEFOG\n"
961 "uniform sampler2D Texture_FogMask;\n"
962 "#endif\n"
963 "#ifdef USELIGHTMAP\n"
964 "uniform sampler2D Texture_Lightmap;\n"
965 "#endif\n"
966 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
967 "uniform sampler2D Texture_Deluxemap;\n"
968 "#endif\n"
969 "#ifdef USEREFLECTION\n"
970 "uniform sampler2D Texture_Reflection;\n"
971 "#endif\n"
972 "\n"
973 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
974 "uniform sampler2D Texture_ScreenDepth;\n"
975 "uniform sampler2D Texture_ScreenNormalMap;\n"
976 "#endif\n"
977 "#ifdef USEDEFERREDLIGHTMAP\n"
978 "uniform sampler2D Texture_ScreenDiffuse;\n"
979 "uniform sampler2D Texture_ScreenSpecular;\n"
980 "#endif\n"
981 "\n"
982 "uniform myhalf3 Color_Pants;\n"
983 "uniform myhalf3 Color_Shirt;\n"
984 "uniform myhalf3 FogColor;\n"
985 "\n"
986 "#ifdef USEFOG\n"
987 "uniform float FogRangeRecip;\n"
988 "uniform float FogPlaneViewDist;\n"
989 "uniform float FogHeightFade;\n"
990 "float FogVertex(void)\n"
991 "{\n"
992 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
993 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
994 "       float fogfrac;\n"
995 "#ifdef USEFOGOUTSIDE\n"
996 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
997 "#else\n"
998 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
999 "#endif\n"
1000 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
1001 "}\n"
1002 "#endif\n"
1003 "\n"
1004 "#ifdef USEOFFSETMAPPING\n"
1005 "uniform float OffsetMapping_Scale;\n"
1006 "vec2 OffsetMapping(vec2 TexCoord)\n"
1007 "{\n"
1008 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1009 "       // 14 sample relief mapping: linear search and then binary search\n"
1010 "       // this basically steps forward a small amount repeatedly until it finds\n"
1011 "       // itself inside solid, then jitters forward and back using decreasing\n"
1012 "       // amounts to find the impact\n"
1013 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1014 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1015 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1016 "       vec3 RT = vec3(TexCoord, 1);\n"
1017 "       OffsetVector *= 0.1;\n"
1018 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1019 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1020 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1021 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1022 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1023 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1024 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1025 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1026 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1027 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1028 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1029 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1030 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1031 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1032 "       return RT.xy;\n"
1033 "#else\n"
1034 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1035 "       // this basically moves forward the full distance, and then backs up based\n"
1036 "       // on height of samples\n"
1037 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1038 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1039 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1040 "       TexCoord += OffsetVector;\n"
1041 "       OffsetVector *= 0.333;\n"
1042 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1043 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1044 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1045 "       return TexCoord;\n"
1046 "#endif\n"
1047 "}\n"
1048 "#endif // USEOFFSETMAPPING\n"
1049 "\n"
1050 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1051 "uniform sampler2D Texture_Attenuation;\n"
1052 "uniform samplerCube Texture_Cube;\n"
1053 "#endif\n"
1054 "\n"
1055 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1056 "\n"
1057 "#ifdef USESHADOWMAPRECT\n"
1058 "# ifdef USESHADOWSAMPLER\n"
1059 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1060 "# else\n"
1061 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1062 "# endif\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef USESHADOWMAP2D\n"
1066 "# ifdef USESHADOWSAMPLER\n"
1067 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1068 "# else\n"
1069 "uniform sampler2D Texture_ShadowMap2D;\n"
1070 "# endif\n"
1071 "#endif\n"
1072 "\n"
1073 "#ifdef USESHADOWMAPVSDCT\n"
1074 "uniform samplerCube Texture_CubeProjection;\n"
1075 "#endif\n"
1076 "\n"
1077 "#ifdef USESHADOWMAPCUBE\n"
1078 "# ifdef USESHADOWSAMPLER\n"
1079 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1080 "# else\n"
1081 "uniform samplerCube Texture_ShadowMapCube;\n"
1082 "# endif\n"
1083 "#endif\n"
1084 "\n"
1085 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1086 "uniform vec2 ShadowMap_TextureScale;\n"
1087 "uniform vec4 ShadowMap_Parameters;\n"
1088 "#endif\n"
1089 "\n"
1090 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1091 "# ifdef USESHADOWMAPORTHO\n"
1092 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1093 "# else\n"
1094 "#  ifdef USESHADOWMAPVSDCT\n"
1095 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1096 "{\n"
1097 "       vec3 adir = abs(dir);\n"
1098 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1099 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1100 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1101 "}\n"
1102 "#  else\n"
1103 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1104 "{\n"
1105 "       vec3 adir = abs(dir);\n"
1106 "       float ma = adir.z;\n"
1107 "       vec4 proj = vec4(dir, 2.5);\n"
1108 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1109 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1110 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1111 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1112 "}\n"
1113 "#  endif\n"
1114 "# endif\n"
1115 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1116 "\n"
1117 "#ifdef USESHADOWMAPCUBE\n"
1118 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1119 "{\n"
1120 "       vec3 adir = abs(dir);\n"
1121 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1122 "}\n"
1123 "#endif\n"
1124 "\n"
1125 "# ifdef USESHADOWMAPRECT\n"
1126 "float ShadowMapCompare(vec3 dir)\n"
1127 "{\n"
1128 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1129 "       float f;\n"
1130 "#  ifdef USESHADOWSAMPLER\n"
1131 "\n"
1132 "#    ifdef USESHADOWMAPPCF\n"
1133 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1134 "       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"
1135 "#    else\n"
1136 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1137 "#    endif\n"
1138 "\n"
1139 "#  else\n"
1140 "\n"
1141 "#    ifdef USESHADOWMAPPCF\n"
1142 "#      if USESHADOWMAPPCF > 1\n"
1143 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1144 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1145 "       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"
1146 "       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"
1147 "       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"
1148 "       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"
1149 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1150 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1151 "#      else\n"
1152 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1153 "       vec2 offset = fract(shadowmaptc.xy);\n"
1154 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1155 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1156 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1157 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1158 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1159 "#      endif\n"
1160 "#    else\n"
1161 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1162 "#    endif\n"
1163 "\n"
1164 "#  endif\n"
1165 "#  ifdef USESHADOWMAPORTHO\n"
1166 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1167 "#  else\n"
1168 "       return f;\n"
1169 "#  endif\n"
1170 "}\n"
1171 "# endif\n"
1172 "\n"
1173 "# ifdef USESHADOWMAP2D\n"
1174 "float ShadowMapCompare(vec3 dir)\n"
1175 "{\n"
1176 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1177 "       float f;\n"
1178 "\n"
1179 "#  ifdef USESHADOWSAMPLER\n"
1180 "#    ifdef USESHADOWMAPPCF\n"
1181 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1182 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1183 "       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"
1184 "#    else\n"
1185 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1186 "#    endif\n"
1187 "#  else\n"
1188 "#    ifdef USESHADOWMAPPCF\n"
1189 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1190 "#      ifdef GL_ARB_texture_gather\n"
1191 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1192 "#      else\n"
1193 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1194 "#      endif\n"
1195 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1196 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1197 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1198 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1199 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1200 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1201 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1202 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1203 "#     else\n"
1204 "#      ifdef GL_EXT_gpu_shader4\n"
1205 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1206 "#      else\n"
1207 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1208 "#      endif\n"
1209 "#      if USESHADOWMAPPCF > 1\n"
1210 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1211 "       center *= ShadowMap_TextureScale;\n"
1212 "       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"
1213 "       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"
1214 "       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"
1215 "       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"
1216 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1217 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1218 "#      else\n"
1219 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1220 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1221 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1222 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1223 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1224 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1225 "#      endif\n"
1226 "#     endif\n"
1227 "#    else\n"
1228 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1229 "#    endif\n"
1230 "#  endif\n"
1231 "#  ifdef USESHADOWMAPORTHO\n"
1232 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1233 "#  else\n"
1234 "       return f;\n"
1235 "#  endif\n"
1236 "}\n"
1237 "# endif\n"
1238 "\n"
1239 "# ifdef USESHADOWMAPCUBE\n"
1240 "float ShadowMapCompare(vec3 dir)\n"
1241 "{\n"
1242 "       // apply depth texture cubemap as light filter\n"
1243 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1244 "       float f;\n"
1245 "#  ifdef USESHADOWSAMPLER\n"
1246 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1247 "#  else\n"
1248 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1249 "#  endif\n"
1250 "       return f;\n"
1251 "}\n"
1252 "# endif\n"
1253 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1254 "#endif // FRAGMENT_SHADER\n"
1255 "\n"
1256 "\n"
1257 "\n"
1258 "\n"
1259 "#ifdef MODE_DEFERREDGEOMETRY\n"
1260 "#ifdef VERTEX_SHADER\n"
1261 "uniform mat4 TexMatrix;\n"
1262 "#ifdef USEVERTEXTEXTUREBLEND\n"
1263 "uniform mat4 BackgroundTexMatrix;\n"
1264 "#endif\n"
1265 "uniform mat4 ModelViewMatrix;\n"
1266 "void main(void)\n"
1267 "{\n"
1268 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1269 "#ifdef USEVERTEXTEXTUREBLEND\n"
1270 "       gl_FrontColor = gl_Color;\n"
1271 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1272 "#endif\n"
1273 "\n"
1274 "       // transform unnormalized eye direction into tangent space\n"
1275 "#ifdef USEOFFSETMAPPING\n"
1276 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1277 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1278 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1279 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1280 "#endif\n"
1281 "\n"
1282 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1283 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1284 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1285 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1286 "}\n"
1287 "#endif // VERTEX_SHADER\n"
1288 "\n"
1289 "#ifdef FRAGMENT_SHADER\n"
1290 "void main(void)\n"
1291 "{\n"
1292 "#ifdef USEOFFSETMAPPING\n"
1293 "       // apply offsetmapping\n"
1294 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1295 "#define TexCoord TexCoordOffset\n"
1296 "#endif\n"
1297 "\n"
1298 "#ifdef USEALPHAKILL\n"
1299 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1300 "               discard;\n"
1301 "#endif\n"
1302 "\n"
1303 "#ifdef USEVERTEXTEXTUREBLEND\n"
1304 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1305 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1306 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1307 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1308 "#endif\n"
1309 "\n"
1310 "#ifdef USEVERTEXTEXTUREBLEND\n"
1311 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1312 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1313 "#else\n"
1314 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1315 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1316 "#endif\n"
1317 "\n"
1318 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1319 "}\n"
1320 "#endif // FRAGMENT_SHADER\n"
1321 "#else // !MODE_DEFERREDGEOMETRY\n"
1322 "\n"
1323 "\n"
1324 "\n"
1325 "\n"
1326 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1327 "#ifdef VERTEX_SHADER\n"
1328 "uniform mat4 ModelViewMatrix;\n"
1329 "void main(void)\n"
1330 "{\n"
1331 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1332 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1333 "}\n"
1334 "#endif // VERTEX_SHADER\n"
1335 "\n"
1336 "#ifdef FRAGMENT_SHADER\n"
1337 "uniform mat4 ViewToLight;\n"
1338 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1339 "uniform vec2 ScreenToDepth;\n"
1340 "uniform myhalf3 DeferredColor_Ambient;\n"
1341 "uniform myhalf3 DeferredColor_Diffuse;\n"
1342 "#ifdef USESPECULAR\n"
1343 "uniform myhalf3 DeferredColor_Specular;\n"
1344 "uniform myhalf SpecularPower;\n"
1345 "#endif\n"
1346 "uniform myhalf2 PixelToScreenTexCoord;\n"
1347 "void main(void)\n"
1348 "{\n"
1349 "       // calculate viewspace pixel position\n"
1350 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1351 "       vec3 position;\n"
1352 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1353 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1354 "       // decode viewspace pixel normal\n"
1355 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1356 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1357 "       // surfacenormal = pixel normal in viewspace\n"
1358 "       // LightVector = pixel to light in viewspace\n"
1359 "       // CubeVector = position in lightspace\n"
1360 "       // eyevector = pixel to view in viewspace\n"
1361 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1362 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1363 "#ifdef USEDIFFUSE\n"
1364 "       // calculate diffuse shading\n"
1365 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1366 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1367 "#endif\n"
1368 "#ifdef USESPECULAR\n"
1369 "       // calculate directional shading\n"
1370 "       vec3 eyevector = position * -1.0;\n"
1371 "#  ifdef USEEXACTSPECULARMATH\n"
1372 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1373 "#  else\n"
1374 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1375 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1376 "#  endif\n"
1377 "#endif\n"
1378 "\n"
1379 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1380 "       fade *= ShadowMapCompare(CubeVector);\n"
1381 "#endif\n"
1382 "\n"
1383 "#ifdef USEDIFFUSE\n"
1384 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1385 "#else\n"
1386 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1387 "#endif\n"
1388 "#ifdef USESPECULAR\n"
1389 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1390 "#else\n"
1391 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1392 "#endif\n"
1393 "\n"
1394 "# ifdef USECUBEFILTER\n"
1395 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1396 "       gl_FragData[0].rgb *= cubecolor;\n"
1397 "       gl_FragData[1].rgb *= cubecolor;\n"
1398 "# endif\n"
1399 "}\n"
1400 "#endif // FRAGMENT_SHADER\n"
1401 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1402 "\n"
1403 "\n"
1404 "\n"
1405 "\n"
1406 "#ifdef VERTEX_SHADER\n"
1407 "uniform mat4 TexMatrix;\n"
1408 "#ifdef USEVERTEXTEXTUREBLEND\n"
1409 "uniform mat4 BackgroundTexMatrix;\n"
1410 "#endif\n"
1411 "#ifdef MODE_LIGHTSOURCE\n"
1412 "uniform mat4 ModelToLight;\n"
1413 "#endif\n"
1414 "#ifdef USESHADOWMAPORTHO\n"
1415 "uniform mat4 ShadowMapMatrix;\n"
1416 "#endif\n"
1417 "void main(void)\n"
1418 "{\n"
1419 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1420 "       gl_FrontColor = gl_Color;\n"
1421 "#endif\n"
1422 "       // copy the surface texcoord\n"
1423 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1424 "#ifdef USEVERTEXTEXTUREBLEND\n"
1425 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1426 "#endif\n"
1427 "#ifdef USELIGHTMAP\n"
1428 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef MODE_LIGHTSOURCE\n"
1432 "       // transform vertex position into light attenuation/cubemap space\n"
1433 "       // (-1 to +1 across the light box)\n"
1434 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1435 "\n"
1436 "# ifdef USEDIFFUSE\n"
1437 "       // transform unnormalized light direction into tangent space\n"
1438 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1439 "       //  normalize it per pixel)\n"
1440 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1441 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1442 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1443 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1444 "# endif\n"
1445 "#endif\n"
1446 "\n"
1447 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1448 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1449 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1450 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1451 "#endif\n"
1452 "\n"
1453 "       // transform unnormalized eye direction into tangent space\n"
1454 "#ifdef USEEYEVECTOR\n"
1455 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1456 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1457 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1458 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1459 "#endif\n"
1460 "\n"
1461 "#ifdef USEFOG\n"
1462 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1463 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1464 "#endif\n"
1465 "\n"
1466 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1467 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1468 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1469 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1470 "#endif\n"
1471 "\n"
1472 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1473 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1474 "\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1477 "#endif\n"
1478 "\n"
1479 "#ifdef USEREFLECTION\n"
1480 "       ModelViewProjectionPosition = gl_Position;\n"
1481 "#endif\n"
1482 "}\n"
1483 "#endif // VERTEX_SHADER\n"
1484 "\n"
1485 "\n"
1486 "\n"
1487 "\n"
1488 "#ifdef FRAGMENT_SHADER\n"
1489 "#ifdef USEDEFERREDLIGHTMAP\n"
1490 "uniform myhalf2 PixelToScreenTexCoord;\n"
1491 "uniform myhalf3 DeferredMod_Diffuse;\n"
1492 "uniform myhalf3 DeferredMod_Specular;\n"
1493 "#endif\n"
1494 "uniform myhalf3 Color_Ambient;\n"
1495 "uniform myhalf3 Color_Diffuse;\n"
1496 "uniform myhalf3 Color_Specular;\n"
1497 "uniform myhalf SpecularPower;\n"
1498 "#ifdef USEGLOW\n"
1499 "uniform myhalf3 Color_Glow;\n"
1500 "#endif\n"
1501 "uniform myhalf Alpha;\n"
1502 "#ifdef USEREFLECTION\n"
1503 "uniform vec4 DistortScaleRefractReflect;\n"
1504 "uniform vec4 ScreenScaleRefractReflect;\n"
1505 "uniform vec4 ScreenCenterRefractReflect;\n"
1506 "uniform myhalf4 ReflectColor;\n"
1507 "#endif\n"
1508 "#ifdef USEREFLECTCUBE\n"
1509 "uniform mat4 ModelToReflectCube;\n"
1510 "uniform sampler2D Texture_ReflectMask;\n"
1511 "uniform samplerCube Texture_ReflectCube;\n"
1512 "#endif\n"
1513 "#ifdef MODE_LIGHTDIRECTION\n"
1514 "uniform myhalf3 LightColor;\n"
1515 "#endif\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 "uniform myhalf3 LightColor;\n"
1518 "#endif\n"
1519 "void main(void)\n"
1520 "{\n"
1521 "#ifdef USEOFFSETMAPPING\n"
1522 "       // apply offsetmapping\n"
1523 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1524 "#define TexCoord TexCoordOffset\n"
1525 "#endif\n"
1526 "\n"
1527 "       // combine the diffuse textures (base, pants, shirt)\n"
1528 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1529 "#ifdef USEALPHAKILL\n"
1530 "       if (color.a < 0.5)\n"
1531 "               discard;\n"
1532 "#endif\n"
1533 "       color.a *= Alpha;\n"
1534 "#ifdef USECOLORMAPPING\n"
1535 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1536 "#endif\n"
1537 "#ifdef USEVERTEXTEXTUREBLEND\n"
1538 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1539 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1540 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1541 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1542 "       color.a = 1.0;\n"
1543 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1544 "#endif\n"
1545 "\n"
1546 "       // get the surface normal\n"
1547 "#ifdef USEVERTEXTEXTUREBLEND\n"
1548 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1549 "#else\n"
1550 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1551 "#endif\n"
1552 "\n"
1553 "       // get the material colors\n"
1554 "       myhalf3 diffusetex = color.rgb;\n"
1555 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1556 "# ifdef USEVERTEXTEXTUREBLEND\n"
1557 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1558 "# else\n"
1559 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1560 "# endif\n"
1561 "#endif\n"
1562 "\n"
1563 "#ifdef USEREFLECTCUBE\n"
1564 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1565 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1566 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1567 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1568 "#endif\n"
1569 "\n"
1570 "\n"
1571 "\n"
1572 "\n"
1573 "#ifdef MODE_LIGHTSOURCE\n"
1574 "       // light source\n"
1575 "#ifdef USEDIFFUSE\n"
1576 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1577 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1578 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1579 "#ifdef USESPECULAR\n"
1580 "#ifdef USEEXACTSPECULARMATH\n"
1581 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1582 "#else\n"
1583 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1584 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1585 "#endif\n"
1586 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1587 "#endif\n"
1588 "#else\n"
1589 "       color.rgb = diffusetex * Color_Ambient;\n"
1590 "#endif\n"
1591 "       color.rgb *= LightColor;\n"
1592 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1593 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1594 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1595 "#endif\n"
1596 "# ifdef USECUBEFILTER\n"
1597 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1598 "# endif\n"
1599 "#endif // MODE_LIGHTSOURCE\n"
1600 "\n"
1601 "\n"
1602 "\n"
1603 "\n"
1604 "#ifdef MODE_LIGHTDIRECTION\n"
1605 "#define SHADING\n"
1606 "#ifdef USEDIFFUSE\n"
1607 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1608 "#endif\n"
1609 "#define lightcolor LightColor\n"
1610 "#endif // MODE_LIGHTDIRECTION\n"
1611 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1612 "#define SHADING\n"
1613 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1614 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1615 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1616 "       // convert modelspace light vector to tangentspace\n"
1617 "       myhalf3 lightnormal;\n"
1618 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1619 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1620 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1621 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1622 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1623 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1624 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1625 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1626 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1627 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1628 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1629 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1630 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1631 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1632 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1633 "#define SHADING\n"
1634 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1635 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1636 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1637 "#endif\n"
1638 "\n"
1639 "\n"
1640 "\n"
1641 "\n"
1642 "#ifdef MODE_LIGHTMAP\n"
1643 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1644 "#endif // MODE_LIGHTMAP\n"
1645 "#ifdef MODE_VERTEXCOLOR\n"
1646 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1647 "#endif // MODE_VERTEXCOLOR\n"
1648 "#ifdef MODE_FLATCOLOR\n"
1649 "       color.rgb = diffusetex * Color_Ambient;\n"
1650 "#endif // MODE_FLATCOLOR\n"
1651 "\n"
1652 "\n"
1653 "\n"
1654 "\n"
1655 "#ifdef SHADING\n"
1656 "# ifdef USEDIFFUSE\n"
1657 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1658 "#  ifdef USESPECULAR\n"
1659 "#   ifdef USEEXACTSPECULARMATH\n"
1660 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1661 "#   else\n"
1662 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1663 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1664 "#   endif\n"
1665 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1666 "#  else\n"
1667 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1668 "#  endif\n"
1669 "# else\n"
1670 "       color.rgb = diffusetex * Color_Ambient;\n"
1671 "# endif\n"
1672 "#endif\n"
1673 "\n"
1674 "#ifdef USESHADOWMAPORTHO\n"
1675 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1676 "#endif\n"
1677 "\n"
1678 "#ifdef USEDEFERREDLIGHTMAP\n"
1679 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1680 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1681 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1682 "#endif\n"
1683 "\n"
1684 "#ifdef USEGLOW\n"
1685 "#ifdef USEVERTEXTEXTUREBLEND\n"
1686 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1687 "#else\n"
1688 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1689 "#endif\n"
1690 "#endif\n"
1691 "\n"
1692 "#ifdef USEFOG\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       color.rgb *= myhalf(FogVertex());\n"
1695 "#else\n"
1696 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1697 "#endif\n"
1698 "#endif\n"
1699 "\n"
1700 "       // 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"
1701 "#ifdef USEREFLECTION\n"
1702 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1703 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1704 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1705 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1706 "       // FIXME temporary hack to detect the case that the reflection\n"
1707 "       // gets blackened at edges due to leaving the area that contains actual\n"
1708 "       // content.\n"
1709 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1710 "       // 'appening.\n"
1711 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1712 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1713 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1714 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1715 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1716 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1717 "#endif\n"
1718 "\n"
1719 "       gl_FragColor = vec4(color);\n"
1720 "}\n"
1721 "#endif // FRAGMENT_SHADER\n"
1722 "\n"
1723 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1724 "#endif // !MODE_DEFERREDGEOMETRY\n"
1725 "#endif // !MODE_WATER\n"
1726 "#endif // !MODE_REFRACTION\n"
1727 "#endif // !MODE_BLOOMBLUR\n"
1728 "#endif // !MODE_GENERIC\n"
1729 "#endif // !MODE_POSTPROCESS\n"
1730 "#endif // !MODE_SHOWDEPTH\n"
1731 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1732 ;
1733
1734 /*
1735 =========================================================================================================================================================
1736
1737
1738
1739 =========================================================================================================================================================
1740
1741
1742
1743 =========================================================================================================================================================
1744
1745
1746
1747 =========================================================================================================================================================
1748
1749
1750
1751 =========================================================================================================================================================
1752
1753
1754
1755 =========================================================================================================================================================
1756
1757
1758
1759 =========================================================================================================================================================
1760 */
1761
1762 const char *builtincgshaderstring =
1763 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1764 "// written by Forest 'LordHavoc' Hale\n"
1765 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1766 "\n"
1767 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1768 "# define USEFOG\n"
1769 "#endif\n"
1770 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1771 "#define USELIGHTMAP\n"
1772 "#endif\n"
1773 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1774 "#define USEEYEVECTOR\n"
1775 "#endif\n"
1776 "\n"
1777 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1778 "#ifdef VERTEX_SHADER\n"
1779 "void main\n"
1780 "(\n"
1781 "float4 gl_Vertex : POSITION,\n"
1782 "uniform float4x4 ModelViewProjectionMatrix,\n"
1783 "out float4 gl_Position : POSITION\n"
1784 ")\n"
1785 "{\n"
1786 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1787 "}\n"
1788 "#endif\n"
1789 "#else // !MODE_DEPTH_ORSHADOW\n"
1790 "\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "#ifdef MODE_SHOWDEPTH\n"
1795 "#ifdef VERTEX_SHADER\n"
1796 "void main\n"
1797 "(\n"
1798 "float4 gl_Vertex : POSITION,\n"
1799 "uniform float4x4 ModelViewProjectionMatrix,\n"
1800 "out float4 gl_Position : POSITION,\n"
1801 "out float4 gl_FrontColor : COLOR0\n"
1802 ")\n"
1803 "{\n"
1804 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1805 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1806 "}\n"
1807 "#endif\n"
1808 "\n"
1809 "#ifdef FRAGMENT_SHADER\n"
1810 "void main\n"
1811 "(\n"
1812 "float4 gl_FrontColor : COLOR0,\n"
1813 "out float4 gl_FragColor : COLOR\n"
1814 ")\n"
1815 "{\n"
1816 "       gl_FragColor = gl_FrontColor;\n"
1817 "}\n"
1818 "#endif\n"
1819 "#else // !MODE_SHOWDEPTH\n"
1820 "\n"
1821 "\n"
1822 "\n"
1823 "\n"
1824 "#ifdef MODE_POSTPROCESS\n"
1825 "\n"
1826 "#ifdef VERTEX_SHADER\n"
1827 "void main\n"
1828 "(\n"
1829 "float4 gl_Vertex : POSITION,\n"
1830 "uniform float4x4 ModelViewProjectionMatrix,\n"
1831 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1832 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1833 "out float4 gl_Position : POSITION,\n"
1834 "out float2 TexCoord1 : TEXCOORD0,\n"
1835 "out float2 TexCoord2 : TEXCOORD1\n"
1836 ")\n"
1837 "{\n"
1838 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1839 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1840 "#ifdef USEBLOOM\n"
1841 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1842 "#endif\n"
1843 "}\n"
1844 "#endif\n"
1845 "\n"
1846 "#ifdef FRAGMENT_SHADER\n"
1847 "void main\n"
1848 "(\n"
1849 "float2 TexCoord1 : TEXCOORD0,\n"
1850 "float2 TexCoord2 : TEXCOORD1,\n"
1851 "uniform sampler2D Texture_First,\n"
1852 "#ifdef USEBLOOM\n"
1853 "uniform sampler2D Texture_Second,\n"
1854 "#endif\n"
1855 "#ifdef USEGAMMARAMPS\n"
1856 "uniform sampler2D Texture_GammaRamps,\n"
1857 "#endif\n"
1858 "#ifdef USESATURATION\n"
1859 "uniform float Saturation,\n"
1860 "#endif\n"
1861 "#ifdef USEVIEWTINT\n"
1862 "uniform float4 ViewTintColor,\n"
1863 "#endif\n"
1864 "uniform float4 UserVec1,\n"
1865 "uniform float4 UserVec2,\n"
1866 "uniform float4 UserVec3,\n"
1867 "uniform float4 UserVec4,\n"
1868 "uniform float ClientTime,\n"
1869 "uniform float2 PixelSize,\n"
1870 "out float4 gl_FragColor : COLOR\n"
1871 ")\n"
1872 "{\n"
1873 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1874 "#ifdef USEBLOOM\n"
1875 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1876 "#endif\n"
1877 "#ifdef USEVIEWTINT\n"
1878 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1879 "#endif\n"
1880 "\n"
1881 "#ifdef USEPOSTPROCESSING\n"
1882 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1883 "// 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"
1884 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1885 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1886 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1887 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1888 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1889 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1890 "#endif\n"
1891 "\n"
1892 "#ifdef USESATURATION\n"
1893 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1894 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1895 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1896 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1897 "#endif\n"
1898 "\n"
1899 "#ifdef USEGAMMARAMPS\n"
1900 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1901 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1902 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1903 "#endif\n"
1904 "}\n"
1905 "#endif\n"
1906 "#else // !MODE_POSTPROCESS\n"
1907 "\n"
1908 "\n"
1909 "\n"
1910 "\n"
1911 "#ifdef MODE_GENERIC\n"
1912 "#ifdef VERTEX_SHADER\n"
1913 "void main\n"
1914 "(\n"
1915 "float4 gl_Vertex : POSITION,\n"
1916 "uniform float4x4 ModelViewProjectionMatrix,\n"
1917 "float4 gl_Color : COLOR0,\n"
1918 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1919 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1920 "out float4 gl_Position : POSITION,\n"
1921 "out float4 gl_FrontColor : COLOR,\n"
1922 "out float2 TexCoord1 : TEXCOORD0,\n"
1923 "out float2 TexCoord2 : TEXCOORD1\n"
1924 ")\n"
1925 "{\n"
1926 "       gl_FrontColor = gl_Color;\n"
1927 "#ifdef USEDIFFUSE\n"
1928 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1929 "#endif\n"
1930 "#ifdef USESPECULAR\n"
1931 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1932 "#endif\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 "float4 gl_FrontColor : COLOR,\n"
1942 "float2 TexCoord1 : TEXCOORD0,\n"
1943 "float2 TexCoord2 : TEXCOORD1,\n"
1944 "#ifdef USEDIFFUSE\n"
1945 "uniform sampler2D Texture_First,\n"
1946 "#endif\n"
1947 "#ifdef USESPECULAR\n"
1948 "uniform sampler2D Texture_Second,\n"
1949 "#endif\n"
1950 "out float4 gl_FragColor : COLOR\n"
1951 ")\n"
1952 "{\n"
1953 "       gl_FragColor = gl_FrontColor;\n"
1954 "#ifdef USEDIFFUSE\n"
1955 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1956 "#endif\n"
1957 "\n"
1958 "#ifdef USESPECULAR\n"
1959 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1960 "# ifdef USECOLORMAPPING\n"
1961 "       gl_FragColor *= tex2;\n"
1962 "# endif\n"
1963 "# ifdef USEGLOW\n"
1964 "       gl_FragColor += tex2;\n"
1965 "# endif\n"
1966 "# ifdef USEVERTEXTEXTUREBLEND\n"
1967 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1968 "# endif\n"
1969 "#endif\n"
1970 "}\n"
1971 "#endif\n"
1972 "#else // !MODE_GENERIC\n"
1973 "\n"
1974 "\n"
1975 "\n"
1976 "\n"
1977 "#ifdef MODE_BLOOMBLUR\n"
1978 "#ifdef VERTEX_SHADER\n"
1979 "void main\n"
1980 "(\n"
1981 "float4 gl_Vertex : POSITION,\n"
1982 "uniform float4x4 ModelViewProjectionMatrix,\n"
1983 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1984 "out float4 gl_Position : POSITION,\n"
1985 "out float2 TexCoord : TEXCOORD0\n"
1986 ")\n"
1987 "{\n"
1988 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1989 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1990 "}\n"
1991 "#endif\n"
1992 "\n"
1993 "#ifdef FRAGMENT_SHADER\n"
1994 "\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord : TEXCOORD0,\n"
1998 "uniform sampler2D Texture_First,\n"
1999 "uniform float4 BloomBlur_Parameters,\n"
2000 "out float4 gl_FragColor : COLOR\n"
2001 ")\n"
2002 "{\n"
2003 "       int i;\n"
2004 "       float2 tc = TexCoord;\n"
2005 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2006 "       tc += BloomBlur_Parameters.xy;\n"
2007 "       for (i = 1;i < SAMPLES;i++)\n"
2008 "       {\n"
2009 "               color += tex2D(Texture_First, tc).rgb;\n"
2010 "               tc += BloomBlur_Parameters.xy;\n"
2011 "       }\n"
2012 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2013 "}\n"
2014 "#endif\n"
2015 "#else // !MODE_BLOOMBLUR\n"
2016 "#ifdef MODE_REFRACTION\n"
2017 "#ifdef VERTEX_SHADER\n"
2018 "void main\n"
2019 "(\n"
2020 "float4 gl_Vertex : POSITION,\n"
2021 "uniform float4x4 ModelViewProjectionMatrix,\n"
2022 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2023 "uniform float4x4 TexMatrix,\n"
2024 "uniform float3 EyePosition,\n"
2025 "out float4 gl_Position : POSITION,\n"
2026 "out float2 TexCoord : TEXCOORD0,\n"
2027 "out float3 EyeVector : TEXCOORD1,\n"
2028 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2029 ")\n"
2030 "{\n"
2031 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2032 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2033 "       ModelViewProjectionPosition = gl_Position;\n"
2034 "}\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef FRAGMENT_SHADER\n"
2038 "void main\n"
2039 "(\n"
2040 "float2 TexCoord : TEXCOORD0,\n"
2041 "float3 EyeVector : TEXCOORD1,\n"
2042 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2043 "uniform sampler2D Texture_Normal,\n"
2044 "uniform sampler2D Texture_Refraction,\n"
2045 "uniform sampler2D Texture_Reflection,\n"
2046 "uniform float4 DistortScaleRefractReflect,\n"
2047 "uniform float4 ScreenScaleRefractReflect,\n"
2048 "uniform float4 ScreenCenterRefractReflect,\n"
2049 "uniform float4 RefractColor,\n"
2050 "out float4 gl_FragColor : COLOR\n"
2051 ")\n"
2052 "{\n"
2053 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2054 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2055 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2056 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2057 "       // FIXME temporary hack to detect the case that the reflection\n"
2058 "       // gets blackened at edges due to leaving the area that contains actual\n"
2059 "       // content.\n"
2060 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2061 "       // 'appening.\n"
2062 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2063 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2064 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2065 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2066 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2067 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2068 "}\n"
2069 "#endif\n"
2070 "#else // !MODE_REFRACTION\n"
2071 "\n"
2072 "\n"
2073 "\n"
2074 "\n"
2075 "#ifdef MODE_WATER\n"
2076 "#ifdef VERTEX_SHADER\n"
2077 "\n"
2078 "void main\n"
2079 "(\n"
2080 "float4 gl_Vertex : POSITION,\n"
2081 "uniform float4x4 ModelViewProjectionMatrix,\n"
2082 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2083 "uniform float4x4 TexMatrix,\n"
2084 "uniform float3 EyePosition,\n"
2085 "out float4 gl_Position : POSITION,\n"
2086 "out float2 TexCoord : TEXCOORD0,\n"
2087 "out float3 EyeVector : TEXCOORD1,\n"
2088 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2089 ")\n"
2090 "{\n"
2091 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2092 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2093 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2094 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2095 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2096 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2097 "       ModelViewProjectionPosition = gl_Position;\n"
2098 "}\n"
2099 "#endif\n"
2100 "\n"
2101 "#ifdef FRAGMENT_SHADER\n"
2102 "void main\n"
2103 "(\n"
2104 "float2 TexCoord : TEXCOORD0,\n"
2105 "float3 EyeVector : TEXCOORD1,\n"
2106 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2107 "uniform sampler2D Texture_Normal,\n"
2108 "uniform sampler2D Texture_Refraction,\n"
2109 "uniform sampler2D Texture_Reflection,\n"
2110 "uniform float4 DistortScaleRefractReflect,\n"
2111 "uniform float4 ScreenScaleRefractReflect,\n"
2112 "uniform float4 ScreenCenterRefractReflect,\n"
2113 "uniform float4 RefractColor,\n"
2114 "uniform float4 ReflectColor,\n"
2115 "uniform float ReflectFactor,\n"
2116 "uniform float ReflectOffset,\n"
2117 "out float4 gl_FragColor : COLOR\n"
2118 ")\n"
2119 "{\n"
2120 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2121 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2122 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2123 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2124 "       // FIXME temporary hack to detect the case that the reflection\n"
2125 "       // gets blackened at edges due to leaving the area that contains actual\n"
2126 "       // content.\n"
2127 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2128 "       // 'appening.\n"
2129 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2130 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2131 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2132 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2133 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2134 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2135 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2136 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2137 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2138 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2139 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2140 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2141 "}\n"
2142 "#endif\n"
2143 "#else // !MODE_WATER\n"
2144 "\n"
2145 "\n"
2146 "\n"
2147 "\n"
2148 "// 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"
2149 "\n"
2150 "// fragment shader specific:\n"
2151 "#ifdef FRAGMENT_SHADER\n"
2152 "\n"
2153 "#ifdef USEFOG\n"
2154 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2155 "{\n"
2156 "       float fogfrac;\n"
2157 "#ifdef USEFOGOUTSIDE\n"
2158 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2159 "#else\n"
2160 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2161 "#endif\n"
2162 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2163 "}\n"
2164 "#endif\n"
2165 "\n"
2166 "#ifdef USEOFFSETMAPPING\n"
2167 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2168 "{\n"
2169 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2170 "       // 14 sample relief mapping: linear search and then binary search\n"
2171 "       // this basically steps forward a small amount repeatedly until it finds\n"
2172 "       // itself inside solid, then jitters forward and back using decreasing\n"
2173 "       // amounts to find the impact\n"
2174 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2175 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2176 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2177 "       float3 RT = float3(TexCoord, 1);\n"
2178 "       OffsetVector *= 0.1;\n"
2179 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2180 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2181 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2182 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2183 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2184 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2185 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2186 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2187 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2188 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2189 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2190 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2191 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2192 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2193 "       return RT.xy;\n"
2194 "#else\n"
2195 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2196 "       // this basically moves forward the full distance, and then backs up based\n"
2197 "       // on height of samples\n"
2198 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2199 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2200 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2201 "       TexCoord += OffsetVector;\n"
2202 "       OffsetVector *= 0.333;\n"
2203 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2204 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2205 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2206 "       return TexCoord;\n"
2207 "#endif\n"
2208 "}\n"
2209 "#endif // USEOFFSETMAPPING\n"
2210 "\n"
2211 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2212 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2213 "# ifdef USESHADOWMAPORTHO\n"
2214 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2215 "# else\n"
2216 "#  ifdef USESHADOWMAPVSDCT\n"
2217 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2218 "{\n"
2219 "       float3 adir = abs(dir);\n"
2220 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2221 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2222 "       return float3(lerp(dir.xy, proj.xy, dir.zz) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2223 "}\n"
2224 "#  else\n"
2225 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2226 "{\n"
2227 "       float3 adir = abs(dir);\n"
2228 "       float ma = adir.z;\n"
2229 "       float4 proj = float4(dir, 2.5);\n"
2230 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2231 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2232 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2233 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2234 "}\n"
2235 "#  endif\n"
2236 "# endif\n"
2237 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2238 "\n"
2239 "#ifdef USESHADOWMAPCUBE\n"
2240 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2241 "{\n"
2242 "    float3 adir = abs(dir);\n"
2243 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2244 "}\n"
2245 "#endif\n"
2246 "\n"
2247 "# ifdef USESHADOWMAPRECT\n"
2248 "#ifdef USESHADOWMAPVSDCT\n"
2249 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2250 "#else\n"
2251 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2252 "#endif\n"
2253 "{\n"
2254 "#ifdef USESHADOWMAPVSDCT\n"
2255 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2256 "#else\n"
2257 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2258 "#endif\n"
2259 "       float f;\n"
2260 "#  ifdef USESHADOWSAMPLER\n"
2261 "\n"
2262 "#    ifdef USESHADOWMAPPCF\n"
2263 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2264 "    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"
2265 "#    else\n"
2266 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2267 "#    endif\n"
2268 "\n"
2269 "#  else\n"
2270 "\n"
2271 "#    ifdef USESHADOWMAPPCF\n"
2272 "#      if USESHADOWMAPPCF > 1\n"
2273 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2274 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2275 "    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"
2276 "    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"
2277 "    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"
2278 "    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"
2279 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2280 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2281 "#      else\n"
2282 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2283 "    float2 offset = frac(shadowmaptc.xy);\n"
2284 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2285 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2286 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2287 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2288 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2289 "#      endif\n"
2290 "#    else\n"
2291 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2292 "#    endif\n"
2293 "\n"
2294 "#  endif\n"
2295 "#  ifdef USESHADOWMAPORTHO\n"
2296 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2297 "#  else\n"
2298 "       return f;\n"
2299 "#  endif\n"
2300 "}\n"
2301 "# endif\n"
2302 "\n"
2303 "# ifdef USESHADOWMAP2D\n"
2304 "#ifdef USESHADOWMAPVSDCT\n"
2305 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2306 "#else\n"
2307 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2308 "#endif\n"
2309 "{\n"
2310 "#ifdef USESHADOWMAPVSDCT\n"
2311 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2312 "#else\n"
2313 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2314 "#endif\n"
2315 "    float f;\n"
2316 "\n"
2317 "#  ifdef USESHADOWSAMPLER\n"
2318 "#    ifdef USESHADOWMAPPCF\n"
2319 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2320 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2321 "    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"
2322 "#    else\n"
2323 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2324 "#    endif\n"
2325 "#  else\n"
2326 "#    ifdef USESHADOWMAPPCF\n"
2327 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2328 "#      ifdef GL_ARB_texture_gather\n"
2329 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
2330 "#      else\n"
2331 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2332 "#      endif\n"
2333 "    float2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2334 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2335 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2336 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2337 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2338 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2339 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2340 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2341 "#     else\n"
2342 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2343 "#      if USESHADOWMAPPCF > 1\n"
2344 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2345 "    center *= ShadowMap_TextureScale;\n"
2346 "    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"
2347 "    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"
2348 "    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"
2349 "    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"
2350 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2351 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2352 "#      else\n"
2353 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2354 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2355 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2356 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2357 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2358 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2359 "#      endif\n"
2360 "#     endif\n"
2361 "#    else\n"
2362 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2363 "#    endif\n"
2364 "#  endif\n"
2365 "#  ifdef USESHADOWMAPORTHO\n"
2366 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2367 "#  else\n"
2368 "       return f;\n"
2369 "#  endif\n"
2370 "}\n"
2371 "# endif\n"
2372 "\n"
2373 "# ifdef USESHADOWMAPCUBE\n"
2374 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2375 "{\n"
2376 "    // apply depth texture cubemap as light filter\n"
2377 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2378 "    float f;\n"
2379 "#  ifdef USESHADOWSAMPLER\n"
2380 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2381 "#  else\n"
2382 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2383 "#  endif\n"
2384 "    return f;\n"
2385 "}\n"
2386 "# endif\n"
2387 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2388 "#endif // FRAGMENT_SHADER\n"
2389 "\n"
2390 "\n"
2391 "\n"
2392 "\n"
2393 "#ifdef MODE_DEFERREDGEOMETRY\n"
2394 "#ifdef VERTEX_SHADER\n"
2395 "void main\n"
2396 "(\n"
2397 "float4 gl_Vertex : POSITION,\n"
2398 "uniform float4x4 ModelViewProjectionMatrix,\n"
2399 "#ifdef USEVERTEXTEXTUREBLEND\n"
2400 "float4 gl_Color : COLOR0,\n"
2401 "#endif\n"
2402 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2403 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2404 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2405 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2406 "uniform float4x4 TexMatrix,\n"
2407 "#ifdef USEVERTEXTEXTUREBLEND\n"
2408 "uniform float4x4 BackgroundTexMatrix,\n"
2409 "#endif\n"
2410 "uniform float4x4 ModelViewMatrix,\n"
2411 "#ifdef USEOFFSETMAPPING\n"
2412 "uniform float3 EyePosition,\n"
2413 "#endif\n"
2414 "out float4 gl_Position : POSITION,\n"
2415 "out float4 gl_FrontColor : COLOR,\n"
2416 "out float4 TexCoordBoth : TEXCOORD0,\n"
2417 "#ifdef USEOFFSETMAPPING\n"
2418 "out float3 EyeVector : TEXCOORD2,\n"
2419 "#endif\n"
2420 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2421 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2422 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2423 ")\n"
2424 "{\n"
2425 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2426 "#ifdef USEVERTEXTEXTUREBLEND\n"
2427 "       gl_FrontColor = gl_Color;\n"
2428 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2429 "#endif\n"
2430 "\n"
2431 "       // transform unnormalized eye direction into tangent space\n"
2432 "#ifdef USEOFFSETMAPPING\n"
2433 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2434 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2435 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2436 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2437 "#endif\n"
2438 "\n"
2439 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2440 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2441 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2442 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2443 "}\n"
2444 "#endif // VERTEX_SHADER\n"
2445 "\n"
2446 "#ifdef FRAGMENT_SHADER\n"
2447 "void main\n"
2448 "(\n"
2449 "float4 TexCoordBoth : TEXCOORD0,\n"
2450 "float3 EyeVector : TEXCOORD2,\n"
2451 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2452 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2453 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2454 "uniform sampler2D Texture_Normal,\n"
2455 "#ifdef USEALPHAKILL\n"
2456 "uniform sampler2D Texture_Color,\n"
2457 "#endif\n"
2458 "uniform sampler2D Texture_Gloss,\n"
2459 "#ifdef USEVERTEXTEXTUREBLEND\n"
2460 "uniform sampler2D Texture_SecondaryNormal,\n"
2461 "uniform sampler2D Texture_SecondaryGloss,\n"
2462 "#endif\n"
2463 "#ifdef USEOFFSETMAPPING\n"
2464 "uniform float OffsetMapping_Scale,\n"
2465 "#endif\n"
2466 "uniform half SpecularPower,\n"
2467 "out float4 gl_FragColor : COLOR\n"
2468 ")\n"
2469 "{\n"
2470 "       float2 TexCoord = TexCoordBoth.xy;\n"
2471 "#ifdef USEOFFSETMAPPING\n"
2472 "       // apply offsetmapping\n"
2473 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2474 "#define TexCoord TexCoordOffset\n"
2475 "#endif\n"
2476 "\n"
2477 "#ifdef USEALPHAKILL\n"
2478 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2479 "               discard;\n"
2480 "#endif\n"
2481 "\n"
2482 "#ifdef USEVERTEXTEXTUREBLEND\n"
2483 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2484 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2485 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2486 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2487 "#endif\n"
2488 "\n"
2489 "#ifdef USEVERTEXTEXTUREBLEND\n"
2490 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2491 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2492 "#else\n"
2493 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2494 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2495 "#endif\n"
2496 "\n"
2497 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2498 "}\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "#else // !MODE_DEFERREDGEOMETRY\n"
2501 "\n"
2502 "\n"
2503 "\n"
2504 "\n"
2505 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2506 "#ifdef VERTEX_SHADER\n"
2507 "void main\n"
2508 "(\n"
2509 "float4 gl_Vertex : POSITION,\n"
2510 "uniform float4x4 ModelViewProjectionMatrix,\n"
2511 "uniform float4x4 ModelViewMatrix,\n"
2512 "out float4 gl_Position : POSITION,\n"
2513 "out float4 ModelViewPosition : TEXCOORD0\n"
2514 ")\n"
2515 "{\n"
2516 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2517 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2518 "}\n"
2519 "#endif // VERTEX_SHADER\n"
2520 "\n"
2521 "#ifdef FRAGMENT_SHADER\n"
2522 "void main\n"
2523 "(\n"
2524 "float2 Pixel : WPOS,\n"
2525 "float4 ModelViewPosition : TEXCOORD0,\n"
2526 "uniform float4x4 ViewToLight,\n"
2527 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2528 "uniform float3 LightPosition,\n"
2529 "uniform half2 PixelToScreenTexCoord,\n"
2530 "uniform half3 DeferredColor_Ambient,\n"
2531 "uniform half3 DeferredColor_Diffuse,\n"
2532 "#ifdef USESPECULAR\n"
2533 "uniform half3 DeferredColor_Specular,\n"
2534 "uniform half SpecularPower,\n"
2535 "#endif\n"
2536 "uniform sampler2D Texture_Attenuation,\n"
2537 "uniform sampler2D Texture_ScreenDepth,\n"
2538 "uniform sampler2D Texture_ScreenNormalMap,\n"
2539 "\n"
2540 "#ifdef USESHADOWMAPRECT\n"
2541 "# ifdef USESHADOWSAMPLER\n"
2542 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2543 "# else\n"
2544 "uniform samplerRECT Texture_ShadowMapRect,\n"
2545 "# endif\n"
2546 "#endif\n"
2547 "\n"
2548 "#ifdef USESHADOWMAP2D\n"
2549 "# ifdef USESHADOWSAMPLER\n"
2550 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2551 "# else\n"
2552 "uniform sampler2D Texture_ShadowMap2D,\n"
2553 "# endif\n"
2554 "#endif\n"
2555 "\n"
2556 "#ifdef USESHADOWMAPVSDCT\n"
2557 "uniform samplerCUBE Texture_CubeProjection,\n"
2558 "#endif\n"
2559 "\n"
2560 "#ifdef USESHADOWMAPCUBE\n"
2561 "# ifdef USESHADOWSAMPLER\n"
2562 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2563 "# else\n"
2564 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2565 "# endif\n"
2566 "#endif\n"
2567 "\n"
2568 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2569 "uniform float2 ShadowMap_TextureScale,\n"
2570 "uniform float4 ShadowMap_Parameters,\n"
2571 "#endif\n"
2572 "\n"
2573 "out float4 gl_FragData0 : COLOR0,\n"
2574 "out float4 gl_FragData1 : COLOR1\n"
2575 ")\n"
2576 "{\n"
2577 "       // calculate viewspace pixel position\n"
2578 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2579 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2580 "       float3 position;\n"
2581 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2582 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2583 "       // decode viewspace pixel normal\n"
2584 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2585 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2586 "       // surfacenormal = pixel normal in viewspace\n"
2587 "       // LightVector = pixel to light in viewspace\n"
2588 "       // CubeVector = position in lightspace\n"
2589 "       // eyevector = pixel to view in viewspace\n"
2590 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2591 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2592 "#ifdef USEDIFFUSE\n"
2593 "       // calculate diffuse shading\n"
2594 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2595 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2596 "#endif\n"
2597 "#ifdef USESPECULAR\n"
2598 "       // calculate directional shading\n"
2599 "       float3 eyevector = position * -1.0;\n"
2600 "#  ifdef USEEXACTSPECULARMATH\n"
2601 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2602 "#  else\n"
2603 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2604 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2605 "#  endif\n"
2606 "#endif\n"
2607 "\n"
2608 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2609 "       fade *= ShadowMapCompare(CubeVector,\n"
2610 "# if defined(USESHADOWMAP2D)\n"
2611 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2612 "# endif\n"
2613 "# if defined(USESHADOWMAPRECT)\n"
2614 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2615 "# endif\n"
2616 "# if defined(USESHADOWMAPCUBE)\n"
2617 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2618 "# endif\n"
2619 "\n"
2620 "#ifdef USESHADOWMAPVSDCT\n"
2621 ", Texture_CubeProjection\n"
2622 "#endif\n"
2623 "       );\n"
2624 "#endif\n"
2625 "\n"
2626 "#ifdef USEDIFFUSE\n"
2627 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2628 "#else\n"
2629 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2630 "#endif\n"
2631 "#ifdef USESPECULAR\n"
2632 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2633 "#else\n"
2634 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2635 "#endif\n"
2636 "\n"
2637 "# ifdef USECUBEFILTER\n"
2638 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2639 "       gl_FragData0.rgb *= cubecolor;\n"
2640 "       gl_FragData1.rgb *= cubecolor;\n"
2641 "# endif\n"
2642 "}\n"
2643 "#endif // FRAGMENT_SHADER\n"
2644 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2645 "\n"
2646 "\n"
2647 "\n"
2648 "\n"
2649 "#ifdef VERTEX_SHADER\n"
2650 "void main\n"
2651 "(\n"
2652 "float4 gl_Vertex : POSITION,\n"
2653 "uniform float4x4 ModelViewProjectionMatrix,\n"
2654 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2655 "float4 gl_Color : COLOR0,\n"
2656 "#endif\n"
2657 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2658 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2659 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2660 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2661 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2662 "\n"
2663 "uniform float3 EyePosition,\n"
2664 "uniform float4x4 TexMatrix,\n"
2665 "#ifdef USEVERTEXTEXTUREBLEND\n"
2666 "uniform float4x4 BackgroundTexMatrix,\n"
2667 "#endif\n"
2668 "#ifdef MODE_LIGHTSOURCE\n"
2669 "uniform float4x4 ModelToLight,\n"
2670 "#endif\n"
2671 "#ifdef MODE_LIGHTSOURCE\n"
2672 "uniform float3 LightPosition,\n"
2673 "#endif\n"
2674 "#ifdef MODE_LIGHTDIRECTION\n"
2675 "uniform float3 LightDir,\n"
2676 "#endif\n"
2677 "uniform float4 FogPlane,\n"
2678 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2679 "uniform float3 LightPosition,\n"
2680 "#endif\n"
2681 "#ifdef USESHADOWMAPORTHO\n"
2682 "uniform float4x4 ShadowMapMatrix,\n"
2683 "#endif\n"
2684 "\n"
2685 "out float4 gl_FrontColor : COLOR,\n"
2686 "out float4 TexCoordBoth : TEXCOORD0,\n"
2687 "#ifdef USELIGHTMAP\n"
2688 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2689 "#endif\n"
2690 "#ifdef USEEYEVECTOR\n"
2691 "out float3 EyeVector : TEXCOORD2,\n"
2692 "#endif\n"
2693 "#ifdef USEREFLECTION\n"
2694 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2695 "#endif\n"
2696 "#ifdef USEFOG\n"
2697 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2698 "#endif\n"
2699 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2700 "out float3 LightVector : TEXCOORD1,\n"
2701 "#endif\n"
2702 "#ifdef MODE_LIGHTSOURCE\n"
2703 "out float3 CubeVector : TEXCOORD3,\n"
2704 "#endif\n"
2705 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2706 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2707 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2708 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2709 "#endif\n"
2710 "#ifdef USESHADOWMAPORTHO\n"
2711 "out float3 ShadowMapTC : TEXCOORD8,\n"
2712 "#endif\n"
2713 "out float4 gl_Position : POSITION\n"
2714 ")\n"
2715 "{\n"
2716 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2717 "       gl_FrontColor = gl_Color;\n"
2718 "#endif\n"
2719 "       // copy the surface texcoord\n"
2720 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2721 "#ifdef USEVERTEXTEXTUREBLEND\n"
2722 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2723 "#endif\n"
2724 "#ifdef USELIGHTMAP\n"
2725 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2726 "#endif\n"
2727 "\n"
2728 "#ifdef MODE_LIGHTSOURCE\n"
2729 "       // transform vertex position into light attenuation/cubemap space\n"
2730 "       // (-1 to +1 across the light box)\n"
2731 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2732 "\n"
2733 "# ifdef USEDIFFUSE\n"
2734 "       // transform unnormalized light direction into tangent space\n"
2735 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2736 "       //  normalize it per pixel)\n"
2737 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2738 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2739 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2740 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2741 "# endif\n"
2742 "#endif\n"
2743 "\n"
2744 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2745 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2746 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2747 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2748 "#endif\n"
2749 "\n"
2750 "       // transform unnormalized eye direction into tangent space\n"
2751 "#ifdef USEEYEVECTOR\n"
2752 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2753 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2754 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2755 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2756 "#endif\n"
2757 "\n"
2758 "#ifdef USEFOG\n"
2759 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2760 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2761 "#endif\n"
2762 "\n"
2763 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2764 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2765 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2766 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2767 "#endif\n"
2768 "\n"
2769 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2770 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2771 "\n"
2772 "#ifdef USESHADOWMAPORTHO\n"
2773 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2774 "#endif\n"
2775 "\n"
2776 "#ifdef USEREFLECTION\n"
2777 "       ModelViewProjectionPosition = gl_Position;\n"
2778 "#endif\n"
2779 "}\n"
2780 "#endif // VERTEX_SHADER\n"
2781 "\n"
2782 "\n"
2783 "\n"
2784 "\n"
2785 "#ifdef FRAGMENT_SHADER\n"
2786 "void main\n"
2787 "(\n"
2788 "#ifdef USEDEFERREDLIGHTMAP\n"
2789 "float2 Pixel : WPOS,\n"
2790 "#endif\n"
2791 "float4 gl_FrontColor : COLOR,\n"
2792 "float4 TexCoordBoth : TEXCOORD0,\n"
2793 "#ifdef USELIGHTMAP\n"
2794 "float2 TexCoordLightmap : TEXCOORD1,\n"
2795 "#endif\n"
2796 "#ifdef USEEYEVECTOR\n"
2797 "float3 EyeVector : TEXCOORD2,\n"
2798 "#endif\n"
2799 "#ifdef USEREFLECTION\n"
2800 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2801 "#endif\n"
2802 "#ifdef USEFOG\n"
2803 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2804 "#endif\n"
2805 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2806 "float3 LightVector : TEXCOORD1,\n"
2807 "#endif\n"
2808 "#ifdef MODE_LIGHTSOURCE\n"
2809 "float3 CubeVector : TEXCOORD3,\n"
2810 "#endif\n"
2811 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2812 "float4 ModelViewPosition : TEXCOORD0,\n"
2813 "#endif\n"
2814 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2815 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2816 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2817 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2818 "#endif\n"
2819 "#ifdef USESHADOWMAPORTHO\n"
2820 "float3 ShadowMapTC : TEXCOORD8,\n"
2821 "#endif\n"
2822 "\n"
2823 "uniform sampler2D Texture_Normal,\n"
2824 "uniform sampler2D Texture_Color,\n"
2825 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2826 "uniform sampler2D Texture_Gloss,\n"
2827 "#endif\n"
2828 "#ifdef USEGLOW\n"
2829 "uniform sampler2D Texture_Glow,\n"
2830 "#endif\n"
2831 "#ifdef USEVERTEXTEXTUREBLEND\n"
2832 "uniform sampler2D Texture_SecondaryNormal,\n"
2833 "uniform sampler2D Texture_SecondaryColor,\n"
2834 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2835 "uniform sampler2D Texture_SecondaryGloss,\n"
2836 "#endif\n"
2837 "#ifdef USEGLOW\n"
2838 "uniform sampler2D Texture_SecondaryGlow,\n"
2839 "#endif\n"
2840 "#endif\n"
2841 "#ifdef USECOLORMAPPING\n"
2842 "uniform sampler2D Texture_Pants,\n"
2843 "uniform sampler2D Texture_Shirt,\n"
2844 "#endif\n"
2845 "#ifdef USEFOG\n"
2846 "uniform sampler2D Texture_FogMask,\n"
2847 "#endif\n"
2848 "#ifdef USELIGHTMAP\n"
2849 "uniform sampler2D Texture_Lightmap,\n"
2850 "#endif\n"
2851 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2852 "uniform sampler2D Texture_Deluxemap,\n"
2853 "#endif\n"
2854 "#ifdef USEREFLECTION\n"
2855 "uniform sampler2D Texture_Reflection,\n"
2856 "#endif\n"
2857 "\n"
2858 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2859 "uniform sampler2D Texture_ScreenDepth,\n"
2860 "uniform sampler2D Texture_ScreenNormalMap,\n"
2861 "#endif\n"
2862 "#ifdef USEDEFERREDLIGHTMAP\n"
2863 "uniform sampler2D Texture_ScreenDiffuse,\n"
2864 "uniform sampler2D Texture_ScreenSpecular,\n"
2865 "#endif\n"
2866 "\n"
2867 "#ifdef USECOLORMAPPING\n"
2868 "uniform half3 Color_Pants,\n"
2869 "uniform half3 Color_Shirt,\n"
2870 "#endif\n"
2871 "#ifdef USEFOG\n"
2872 "uniform float3 FogColor,\n"
2873 "uniform float FogRangeRecip,\n"
2874 "uniform float FogPlaneViewDist,\n"
2875 "uniform float FogHeightFade,\n"
2876 "#endif\n"
2877 "\n"
2878 "#ifdef USEOFFSETMAPPING\n"
2879 "uniform float OffsetMapping_Scale,\n"
2880 "#endif\n"
2881 "\n"
2882 "#ifdef USEDEFERREDLIGHTMAP\n"
2883 "uniform half2 PixelToScreenTexCoord,\n"
2884 "uniform half3 DeferredMod_Diffuse,\n"
2885 "uniform half3 DeferredMod_Specular,\n"
2886 "#endif\n"
2887 "uniform half3 Color_Ambient,\n"
2888 "uniform half3 Color_Diffuse,\n"
2889 "uniform half3 Color_Specular,\n"
2890 "uniform half SpecularPower,\n"
2891 "#ifdef USEGLOW\n"
2892 "uniform half3 Color_Glow,\n"
2893 "#endif\n"
2894 "uniform half Alpha,\n"
2895 "#ifdef USEREFLECTION\n"
2896 "uniform float4 DistortScaleRefractReflect,\n"
2897 "uniform float4 ScreenScaleRefractReflect,\n"
2898 "uniform float4 ScreenCenterRefractReflect,\n"
2899 "uniform half4 ReflectColor,\n"
2900 "#endif\n"
2901 "#ifdef USEREFLECTCUBE\n"
2902 "uniform float4x4 ModelToReflectCube,\n"
2903 "uniform sampler2D Texture_ReflectMask,\n"
2904 "uniform samplerCUBE Texture_ReflectCube,\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTDIRECTION\n"
2907 "uniform half3 LightColor,\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTSOURCE\n"
2910 "uniform half3 LightColor,\n"
2911 "#endif\n"
2912 "\n"
2913 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2914 "uniform sampler2D Texture_Attenuation,\n"
2915 "uniform samplerCUBE Texture_Cube,\n"
2916 "#endif\n"
2917 "\n"
2918 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2919 "\n"
2920 "#ifdef USESHADOWMAPRECT\n"
2921 "# ifdef USESHADOWSAMPLER\n"
2922 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2923 "# else\n"
2924 "uniform samplerRECT Texture_ShadowMapRect,\n"
2925 "# endif\n"
2926 "#endif\n"
2927 "\n"
2928 "#ifdef USESHADOWMAP2D\n"
2929 "# ifdef USESHADOWSAMPLER\n"
2930 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2931 "# else\n"
2932 "uniform sampler2D Texture_ShadowMap2D,\n"
2933 "# endif\n"
2934 "#endif\n"
2935 "\n"
2936 "#ifdef USESHADOWMAPVSDCT\n"
2937 "uniform samplerCUBE Texture_CubeProjection,\n"
2938 "#endif\n"
2939 "\n"
2940 "#ifdef USESHADOWMAPCUBE\n"
2941 "# ifdef USESHADOWSAMPLER\n"
2942 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2943 "# else\n"
2944 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2945 "# endif\n"
2946 "#endif\n"
2947 "\n"
2948 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2949 "uniform float2 ShadowMap_TextureScale,\n"
2950 "uniform float4 ShadowMap_Parameters,\n"
2951 "#endif\n"
2952 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2953 "\n"
2954 "out float4 gl_FragColor : COLOR\n"
2955 ")\n"
2956 "{\n"
2957 "       float2 TexCoord = TexCoordBoth.xy;\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2960 "#endif\n"
2961 "#ifdef USEOFFSETMAPPING\n"
2962 "       // apply offsetmapping\n"
2963 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2964 "#define TexCoord TexCoordOffset\n"
2965 "#endif\n"
2966 "\n"
2967 "       // combine the diffuse textures (base, pants, shirt)\n"
2968 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2969 "#ifdef USEALPHAKILL\n"
2970 "       if (color.a < 0.5)\n"
2971 "               discard;\n"
2972 "#endif\n"
2973 "       color.a *= Alpha;\n"
2974 "#ifdef USECOLORMAPPING\n"
2975 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2976 "#endif\n"
2977 "#ifdef USEVERTEXTEXTUREBLEND\n"
2978 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2979 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2980 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2981 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2982 "       color.a = 1.0;\n"
2983 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2984 "#endif\n"
2985 "\n"
2986 "       // get the surface normal\n"
2987 "#ifdef USEVERTEXTEXTUREBLEND\n"
2988 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2989 "#else\n"
2990 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2991 "#endif\n"
2992 "\n"
2993 "       // get the material colors\n"
2994 "       half3 diffusetex = color.rgb;\n"
2995 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2996 "# ifdef USEVERTEXTEXTUREBLEND\n"
2997 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2998 "# else\n"
2999 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3000 "# endif\n"
3001 "#endif\n"
3002 "\n"
3003 "#ifdef USEREFLECTCUBE\n"
3004 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3005 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3006 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3007 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3008 "#endif\n"
3009 "\n"
3010 "\n"
3011 "\n"
3012 "\n"
3013 "#ifdef MODE_LIGHTSOURCE\n"
3014 "       // light source\n"
3015 "#ifdef USEDIFFUSE\n"
3016 "       half3 lightnormal = half3(normalize(LightVector));\n"
3017 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3018 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3019 "#ifdef USESPECULAR\n"
3020 "#ifdef USEEXACTSPECULARMATH\n"
3021 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3022 "#else\n"
3023 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3024 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3025 "#endif\n"
3026 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3027 "#endif\n"
3028 "#else\n"
3029 "       color.rgb = diffusetex * Color_Ambient;\n"
3030 "#endif\n"
3031 "       color.rgb *= LightColor;\n"
3032 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3033 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3034 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3035 "# if defined(USESHADOWMAP2D)\n"
3036 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3037 "# endif\n"
3038 "# if defined(USESHADOWMAPRECT)\n"
3039 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3040 "# endif\n"
3041 "# if defined(USESHADOWMAPCUBE)\n"
3042 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3043 "# endif\n"
3044 "\n"
3045 "#ifdef USESHADOWMAPVSDCT\n"
3046 ", Texture_CubeProjection\n"
3047 "#endif\n"
3048 "       );\n"
3049 "\n"
3050 "#endif\n"
3051 "# ifdef USECUBEFILTER\n"
3052 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3053 "# endif\n"
3054 "#endif // MODE_LIGHTSOURCE\n"
3055 "\n"
3056 "\n"
3057 "\n"
3058 "\n"
3059 "#ifdef MODE_LIGHTDIRECTION\n"
3060 "#define SHADING\n"
3061 "#ifdef USEDIFFUSE\n"
3062 "       half3 lightnormal = half3(normalize(LightVector));\n"
3063 "#endif\n"
3064 "#define lightcolor LightColor\n"
3065 "#endif // MODE_LIGHTDIRECTION\n"
3066 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3067 "#define SHADING\n"
3068 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3069 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3070 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3071 "       // convert modelspace light vector to tangentspace\n"
3072 "       half3 lightnormal;\n"
3073 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3074 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3075 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3076 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3077 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3078 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3079 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3080 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3081 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3082 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3083 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3084 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3085 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3086 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3087 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3088 "#define SHADING\n"
3089 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3090 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3091 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3092 "#endif\n"
3093 "\n"
3094 "\n"
3095 "\n"
3096 "\n"
3097 "#ifdef MODE_LIGHTMAP\n"
3098 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3099 "#endif // MODE_LIGHTMAP\n"
3100 "#ifdef MODE_VERTEXCOLOR\n"
3101 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3102 "#endif // MODE_VERTEXCOLOR\n"
3103 "#ifdef MODE_FLATCOLOR\n"
3104 "       color.rgb = diffusetex * Color_Ambient;\n"
3105 "#endif // MODE_FLATCOLOR\n"
3106 "\n"
3107 "\n"
3108 "\n"
3109 "\n"
3110 "#ifdef SHADING\n"
3111 "# ifdef USEDIFFUSE\n"
3112 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3113 "#  ifdef USESPECULAR\n"
3114 "#   ifdef USEEXACTSPECULARMATH\n"
3115 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3116 "#   else\n"
3117 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3118 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3119 "#   endif\n"
3120 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3121 "#  else\n"
3122 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3123 "#  endif\n"
3124 "# else\n"
3125 "       color.rgb = diffusetex * Color_Ambient;\n"
3126 "# endif\n"
3127 "#endif\n"
3128 "\n"
3129 "#ifdef USESHADOWMAPORTHO\n"
3130 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3131 "# if defined(USESHADOWMAP2D)\n"
3132 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3133 "# endif\n"
3134 "# if defined(USESHADOWMAPRECT)\n"
3135 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3136 "# endif\n"
3137 "       );\n"
3138 "#endif\n"
3139 "\n"
3140 "#ifdef USEDEFERREDLIGHTMAP\n"
3141 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3142 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3143 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3144 "#endif\n"
3145 "\n"
3146 "#ifdef USEGLOW\n"
3147 "#ifdef USEVERTEXTEXTUREBLEND\n"
3148 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3149 "#else\n"
3150 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3151 "#endif\n"
3152 "#endif\n"
3153 "\n"
3154 "#ifdef USEFOG\n"
3155 "#ifdef MODE_LIGHTSOURCE\n"
3156 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3157 "#else\n"
3158 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3159 "#endif\n"
3160 "#endif\n"
3161 "\n"
3162 "       // 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"
3163 "#ifdef USEREFLECTION\n"
3164 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3165 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3166 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3167 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3168 "       // FIXME temporary hack to detect the case that the reflection\n"
3169 "       // gets blackened at edges due to leaving the area that contains actual\n"
3170 "       // content.\n"
3171 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3172 "       // 'appening.\n"
3173 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3174 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3175 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3176 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3177 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3178 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3179 "#endif\n"
3180 "\n"
3181 "       gl_FragColor = float4(color);\n"
3182 "}\n"
3183 "#endif // FRAGMENT_SHADER\n"
3184 "\n"
3185 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3186 "#endif // !MODE_DEFERREDGEOMETRY\n"
3187 "#endif // !MODE_WATER\n"
3188 "#endif // !MODE_REFRACTION\n"
3189 "#endif // !MODE_BLOOMBLUR\n"
3190 "#endif // !MODE_GENERIC\n"
3191 "#endif // !MODE_POSTPROCESS\n"
3192 "#endif // !MODE_SHOWDEPTH\n"
3193 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3194 ;
3195
3196 char *glslshaderstring = NULL;
3197 char *cgshaderstring = NULL;
3198
3199 //=======================================================================================================================================================
3200
3201 typedef struct shaderpermutationinfo_s
3202 {
3203         const char *pretext;
3204         const char *name;
3205 }
3206 shaderpermutationinfo_t;
3207
3208 typedef struct shadermodeinfo_s
3209 {
3210         const char *vertexfilename;
3211         const char *geometryfilename;
3212         const char *fragmentfilename;
3213         const char *pretext;
3214         const char *name;
3215 }
3216 shadermodeinfo_t;
3217
3218 typedef enum shaderpermutation_e
3219 {
3220         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3221         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3222         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3223         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3224         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3225         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3226         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3227         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3228         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3229         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3230         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3231         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3232         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3233         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3234         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3235         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3236         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3237         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3238         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3239         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3240         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3241         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3242         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3243         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3244         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3245         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3246         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3247         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3248         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3249         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3250 }
3251 shaderpermutation_t;
3252
3253 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3254 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3255 {
3256         {"#define USEDIFFUSE\n", " diffuse"},
3257         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3258         {"#define USEVIEWTINT\n", " viewtint"},
3259         {"#define USECOLORMAPPING\n", " colormapping"},
3260         {"#define USESATURATION\n", " saturation"},
3261         {"#define USEFOGINSIDE\n", " foginside"},
3262         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3263         {"#define USEGAMMARAMPS\n", " gammaramps"},
3264         {"#define USECUBEFILTER\n", " cubefilter"},
3265         {"#define USEGLOW\n", " glow"},
3266         {"#define USEBLOOM\n", " bloom"},
3267         {"#define USESPECULAR\n", " specular"},
3268         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3269         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3270         {"#define USEREFLECTION\n", " reflection"},
3271         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3272         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3273         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3274         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3275         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3276         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3277         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3278         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3279         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3280         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3281         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3282         {"#define USEALPHAKILL\n", " alphakill"},
3283         {"#define USEREFLECTCUBE\n", " reflectcube"},
3284 };
3285
3286 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3287 typedef enum shadermode_e
3288 {
3289         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3290         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3291         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3292         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3293         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3294         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3295         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3296         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3297         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3298         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3299         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3300         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3301         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3302         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3303         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3304         SHADERMODE_COUNT
3305 }
3306 shadermode_t;
3307
3308 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3309 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3310 {
3311         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3312         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3313         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3314         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3315         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3316         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3317         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3318         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3319         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3320         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3321         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3322         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3323         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3324         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3325         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3326 };
3327
3328 #ifdef SUPPORTCG
3329 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3330 {
3331         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3332         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3333         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3334         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3335         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3336         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3337         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3338         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3339         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3340         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3341         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3342         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3343         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3344         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3345         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3346 };
3347 #endif
3348
3349 struct r_glsl_permutation_s;
3350 typedef struct r_glsl_permutation_s
3351 {
3352         /// hash lookup data
3353         struct r_glsl_permutation_s *hashnext;
3354         unsigned int mode;
3355         unsigned int permutation;
3356
3357         /// indicates if we have tried compiling this permutation already
3358         qboolean compiled;
3359         /// 0 if compilation failed
3360         int program;
3361         /// locations of detected uniforms in program object, or -1 if not found
3362         int loc_Texture_First;
3363         int loc_Texture_Second;
3364         int loc_Texture_GammaRamps;
3365         int loc_Texture_Normal;
3366         int loc_Texture_Color;
3367         int loc_Texture_Gloss;
3368         int loc_Texture_Glow;
3369         int loc_Texture_SecondaryNormal;
3370         int loc_Texture_SecondaryColor;
3371         int loc_Texture_SecondaryGloss;
3372         int loc_Texture_SecondaryGlow;
3373         int loc_Texture_Pants;
3374         int loc_Texture_Shirt;
3375         int loc_Texture_FogMask;
3376         int loc_Texture_Lightmap;
3377         int loc_Texture_Deluxemap;
3378         int loc_Texture_Attenuation;
3379         int loc_Texture_Cube;
3380         int loc_Texture_Refraction;
3381         int loc_Texture_Reflection;
3382         int loc_Texture_ShadowMapRect;
3383         int loc_Texture_ShadowMapCube;
3384         int loc_Texture_ShadowMap2D;
3385         int loc_Texture_CubeProjection;
3386         int loc_Texture_ScreenDepth;
3387         int loc_Texture_ScreenNormalMap;
3388         int loc_Texture_ScreenDiffuse;
3389         int loc_Texture_ScreenSpecular;
3390         int loc_Texture_ReflectMask;
3391         int loc_Texture_ReflectCube;
3392         int loc_Alpha;
3393         int loc_BloomBlur_Parameters;
3394         int loc_ClientTime;
3395         int loc_Color_Ambient;
3396         int loc_Color_Diffuse;
3397         int loc_Color_Specular;
3398         int loc_Color_Glow;
3399         int loc_Color_Pants;
3400         int loc_Color_Shirt;
3401         int loc_DeferredColor_Ambient;
3402         int loc_DeferredColor_Diffuse;
3403         int loc_DeferredColor_Specular;
3404         int loc_DeferredMod_Diffuse;
3405         int loc_DeferredMod_Specular;
3406         int loc_DistortScaleRefractReflect;
3407         int loc_EyePosition;
3408         int loc_FogColor;
3409         int loc_FogHeightFade;
3410         int loc_FogPlane;
3411         int loc_FogPlaneViewDist;
3412         int loc_FogRangeRecip;
3413         int loc_LightColor;
3414         int loc_LightDir;
3415         int loc_LightPosition;
3416         int loc_OffsetMapping_Scale;
3417         int loc_PixelSize;
3418         int loc_ReflectColor;
3419         int loc_ReflectFactor;
3420         int loc_ReflectOffset;
3421         int loc_RefractColor;
3422         int loc_Saturation;
3423         int loc_ScreenCenterRefractReflect;
3424         int loc_ScreenScaleRefractReflect;
3425         int loc_ScreenToDepth;
3426         int loc_ShadowMap_Parameters;
3427         int loc_ShadowMap_TextureScale;
3428         int loc_SpecularPower;
3429         int loc_UserVec1;
3430         int loc_UserVec2;
3431         int loc_UserVec3;
3432         int loc_UserVec4;
3433         int loc_ViewTintColor;
3434         int loc_ViewToLight;
3435         int loc_ModelToLight;
3436         int loc_TexMatrix;
3437         int loc_BackgroundTexMatrix;
3438         int loc_ModelViewProjectionMatrix;
3439         int loc_ModelViewMatrix;
3440         int loc_PixelToScreenTexCoord;
3441         int loc_ModelToReflectCube;
3442         int loc_ShadowMapMatrix;        
3443 }
3444 r_glsl_permutation_t;
3445
3446 #define SHADERPERMUTATION_HASHSIZE 256
3447
3448 /// information about each possible shader permutation
3449 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3450 /// currently selected permutation
3451 r_glsl_permutation_t *r_glsl_permutation;
3452 /// storage for permutations linked in the hash table
3453 memexpandablearray_t r_glsl_permutationarray;
3454
3455 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3456 {
3457         //unsigned int hashdepth = 0;
3458         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3459         r_glsl_permutation_t *p;
3460         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3461         {
3462                 if (p->mode == mode && p->permutation == permutation)
3463                 {
3464                         //if (hashdepth > 10)
3465                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3466                         return p;
3467                 }
3468                 //hashdepth++;
3469         }
3470         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3471         p->mode = mode;
3472         p->permutation = permutation;
3473         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3474         r_glsl_permutationhash[mode][hashindex] = p;
3475         //if (hashdepth > 10)
3476         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3477         return p;
3478 }
3479
3480 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3481 {
3482         char *shaderstring;
3483         if (!filename || !filename[0])
3484                 return NULL;
3485         if (!strcmp(filename, "glsl/default.glsl"))
3486         {
3487                 if (!glslshaderstring)
3488                 {
3489                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3490                         if (glslshaderstring)
3491                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3492                         else
3493                                 glslshaderstring = (char *)builtinshaderstring;
3494                 }
3495                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3496                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3497                 return shaderstring;
3498         }
3499         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3500         if (shaderstring)
3501         {
3502                 if (printfromdisknotice)
3503                         Con_DPrintf("from disk %s... ", filename);
3504                 return shaderstring;
3505         }
3506         return shaderstring;
3507 }
3508
3509 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3510 {
3511         int i;
3512         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3513         int vertstrings_count = 0;
3514         int geomstrings_count = 0;
3515         int fragstrings_count = 0;
3516         char *vertexstring, *geometrystring, *fragmentstring;
3517         const char *vertstrings_list[32+3];
3518         const char *geomstrings_list[32+3];
3519         const char *fragstrings_list[32+3];
3520         char permutationname[256];
3521
3522         if (p->compiled)
3523                 return;
3524         p->compiled = true;
3525         p->program = 0;
3526
3527         permutationname[0] = 0;
3528         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3529         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3530         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3531
3532         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3533
3534         // the first pretext is which type of shader to compile as
3535         // (later these will all be bound together as a program object)
3536         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3537         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3538         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3539
3540         // the second pretext is the mode (for example a light source)
3541         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3542         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3543         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3544         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3545
3546         // now add all the permutation pretexts
3547         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3548         {
3549                 if (permutation & (1<<i))
3550                 {
3551                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3552                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3553                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3554                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3555                 }
3556                 else
3557                 {
3558                         // keep line numbers correct
3559                         vertstrings_list[vertstrings_count++] = "\n";
3560                         geomstrings_list[geomstrings_count++] = "\n";
3561                         fragstrings_list[fragstrings_count++] = "\n";
3562                 }
3563         }
3564
3565         // now append the shader text itself
3566         vertstrings_list[vertstrings_count++] = vertexstring;
3567         geomstrings_list[geomstrings_count++] = geometrystring;
3568         fragstrings_list[fragstrings_count++] = fragmentstring;
3569
3570         // if any sources were NULL, clear the respective list
3571         if (!vertexstring)
3572                 vertstrings_count = 0;
3573         if (!geometrystring)
3574                 geomstrings_count = 0;
3575         if (!fragmentstring)
3576                 fragstrings_count = 0;
3577
3578         // compile the shader program
3579         if (vertstrings_count + geomstrings_count + fragstrings_count)
3580                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3581         if (p->program)
3582         {
3583                 CHECKGLERROR
3584                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3585                 // look up all the uniform variable names we care about, so we don't
3586                 // have to look them up every time we set them
3587
3588                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3589                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3590                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3591                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3592                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3593                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3594                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3595                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3596                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3597                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3598                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3599                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3600                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3601                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3602                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3603                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3604                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3605                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3606                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3607                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3608                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3609                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3610                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3611                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3612                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3613                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3614                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3615                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3616                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3617                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3618                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3619                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3620                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3621                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3622                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3623                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3624                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3625                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3626                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3627                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3628                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3629                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3630                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3631                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3632                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3633                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3634                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3635                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3636                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3637                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3638                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3639                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3640                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3641                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3642                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3643                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3644                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3645                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3646                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3647                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3648                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3649                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3650                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3651                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3652                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3653                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3654                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3655                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3656                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3657                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3658                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3659                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3660                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3661                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3662                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3663                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3664                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3665                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3666                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3667                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3668                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3669                 // initialize the samplers to refer to the texture units we use
3670                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3671                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3672                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3673                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3674                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3675                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3676                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3677                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3678                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3679                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3680                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3681                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3682                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3683                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3684                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3685                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3686                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3687                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3688                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3689                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3690                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3691                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3692                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3693                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3694                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3695                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3696                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3697                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3698                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3699                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3700                 CHECKGLERROR
3701                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3702         }
3703         else
3704                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3705
3706         // free the strings
3707         if (vertexstring)
3708                 Mem_Free(vertexstring);
3709         if (geometrystring)
3710                 Mem_Free(geometrystring);
3711         if (fragmentstring)
3712                 Mem_Free(fragmentstring);
3713 }
3714
3715 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3716 {
3717         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3718         if (r_glsl_permutation != perm)
3719         {
3720                 r_glsl_permutation = perm;
3721                 if (!r_glsl_permutation->program)
3722                 {
3723                         if (!r_glsl_permutation->compiled)
3724                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3725                         if (!r_glsl_permutation->program)
3726                         {
3727                                 // remove features until we find a valid permutation
3728                                 int i;
3729                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3730                                 {
3731                                         // reduce i more quickly whenever it would not remove any bits
3732                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3733                                         if (!(permutation & j))
3734                                                 continue;
3735                                         permutation -= j;
3736                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3737                                         if (!r_glsl_permutation->compiled)
3738                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3739                                         if (r_glsl_permutation->program)
3740                                                 break;
3741                                 }
3742                                 if (i >= SHADERPERMUTATION_COUNT)
3743                                 {
3744                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3745                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3746                                         qglUseProgramObjectARB(0);CHECKGLERROR
3747                                         return; // no bit left to clear, entire mode is broken
3748                                 }
3749                         }
3750                 }
3751                 CHECKGLERROR
3752                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3753         }
3754         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3755         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3756         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3757 }
3758
3759 #ifdef SUPPORTCG
3760 #include <Cg/cgGL.h>
3761 struct r_cg_permutation_s;
3762 typedef struct r_cg_permutation_s
3763 {
3764         /// hash lookup data
3765         struct r_cg_permutation_s *hashnext;
3766         unsigned int mode;
3767         unsigned int permutation;
3768
3769         /// indicates if we have tried compiling this permutation already
3770         qboolean compiled;
3771         /// 0 if compilation failed
3772         CGprogram vprogram;
3773         CGprogram fprogram;
3774         /// locations of detected parameters in programs, or NULL if not found
3775         CGparameter vp_EyePosition;
3776         CGparameter vp_FogPlane;
3777         CGparameter vp_LightDir;
3778         CGparameter vp_LightPosition;
3779         CGparameter vp_ModelToLight;
3780         CGparameter vp_TexMatrix;
3781         CGparameter vp_BackgroundTexMatrix;
3782         CGparameter vp_ModelViewProjectionMatrix;
3783         CGparameter vp_ModelViewMatrix;
3784         CGparameter vp_ShadowMapMatrix;
3785
3786         CGparameter fp_Texture_First;
3787         CGparameter fp_Texture_Second;
3788         CGparameter fp_Texture_GammaRamps;
3789         CGparameter fp_Texture_Normal;
3790         CGparameter fp_Texture_Color;
3791         CGparameter fp_Texture_Gloss;
3792         CGparameter fp_Texture_Glow;
3793         CGparameter fp_Texture_SecondaryNormal;
3794         CGparameter fp_Texture_SecondaryColor;
3795         CGparameter fp_Texture_SecondaryGloss;
3796         CGparameter fp_Texture_SecondaryGlow;
3797         CGparameter fp_Texture_Pants;
3798         CGparameter fp_Texture_Shirt;
3799         CGparameter fp_Texture_FogMask;
3800         CGparameter fp_Texture_Lightmap;
3801         CGparameter fp_Texture_Deluxemap;
3802         CGparameter fp_Texture_Attenuation;
3803         CGparameter fp_Texture_Cube;
3804         CGparameter fp_Texture_Refraction;
3805         CGparameter fp_Texture_Reflection;
3806         CGparameter fp_Texture_ShadowMapRect;
3807         CGparameter fp_Texture_ShadowMapCube;
3808         CGparameter fp_Texture_ShadowMap2D;
3809         CGparameter fp_Texture_CubeProjection;
3810         CGparameter fp_Texture_ScreenDepth;
3811         CGparameter fp_Texture_ScreenNormalMap;
3812         CGparameter fp_Texture_ScreenDiffuse;
3813         CGparameter fp_Texture_ScreenSpecular;
3814         CGparameter fp_Texture_ReflectMask;
3815         CGparameter fp_Texture_ReflectCube;
3816         CGparameter fp_Alpha;
3817         CGparameter fp_BloomBlur_Parameters;
3818         CGparameter fp_ClientTime;
3819         CGparameter fp_Color_Ambient;
3820         CGparameter fp_Color_Diffuse;
3821         CGparameter fp_Color_Specular;
3822         CGparameter fp_Color_Glow;
3823         CGparameter fp_Color_Pants;
3824         CGparameter fp_Color_Shirt;
3825         CGparameter fp_DeferredColor_Ambient;
3826         CGparameter fp_DeferredColor_Diffuse;
3827         CGparameter fp_DeferredColor_Specular;
3828         CGparameter fp_DeferredMod_Diffuse;
3829         CGparameter fp_DeferredMod_Specular;
3830         CGparameter fp_DistortScaleRefractReflect;
3831         CGparameter fp_EyePosition;
3832         CGparameter fp_FogColor;
3833         CGparameter fp_FogHeightFade;
3834         CGparameter fp_FogPlane;
3835         CGparameter fp_FogPlaneViewDist;
3836         CGparameter fp_FogRangeRecip;
3837         CGparameter fp_LightColor;
3838         CGparameter fp_LightDir;
3839         CGparameter fp_LightPosition;
3840         CGparameter fp_OffsetMapping_Scale;
3841         CGparameter fp_PixelSize;
3842         CGparameter fp_ReflectColor;
3843         CGparameter fp_ReflectFactor;
3844         CGparameter fp_ReflectOffset;
3845         CGparameter fp_RefractColor;
3846         CGparameter fp_Saturation;
3847         CGparameter fp_ScreenCenterRefractReflect;
3848         CGparameter fp_ScreenScaleRefractReflect;
3849         CGparameter fp_ScreenToDepth;
3850         CGparameter fp_ShadowMap_Parameters;
3851         CGparameter fp_ShadowMap_TextureScale;
3852         CGparameter fp_SpecularPower;
3853         CGparameter fp_UserVec1;
3854         CGparameter fp_UserVec2;
3855         CGparameter fp_UserVec3;
3856         CGparameter fp_UserVec4;
3857         CGparameter fp_ViewTintColor;
3858         CGparameter fp_ViewToLight;
3859         CGparameter fp_PixelToScreenTexCoord;
3860         CGparameter fp_ModelToReflectCube;
3861 }
3862 r_cg_permutation_t;
3863
3864 /// information about each possible shader permutation
3865 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3866 /// currently selected permutation
3867 r_cg_permutation_t *r_cg_permutation;
3868 /// storage for permutations linked in the hash table
3869 memexpandablearray_t r_cg_permutationarray;
3870
3871 #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));}}
3872
3873 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3874 {
3875         //unsigned int hashdepth = 0;
3876         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3877         r_cg_permutation_t *p;
3878         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3879         {
3880                 if (p->mode == mode && p->permutation == permutation)
3881                 {
3882                         //if (hashdepth > 10)
3883                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3884                         return p;
3885                 }
3886                 //hashdepth++;
3887         }
3888         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3889         p->mode = mode;
3890         p->permutation = permutation;
3891         p->hashnext = r_cg_permutationhash[mode][hashindex];
3892         r_cg_permutationhash[mode][hashindex] = p;
3893         //if (hashdepth > 10)
3894         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3895         return p;
3896 }
3897
3898 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3899 {
3900         char *shaderstring;
3901         if (!filename || !filename[0])
3902                 return NULL;
3903         if (!strcmp(filename, "cg/default.cg"))
3904         {
3905                 if (!cgshaderstring)
3906                 {
3907                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3908                         if (cgshaderstring)
3909                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3910                         else
3911                                 cgshaderstring = (char *)builtincgshaderstring;
3912                 }
3913                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3914                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3915                 return shaderstring;
3916         }
3917         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3918         if (shaderstring)
3919         {
3920                 if (printfromdisknotice)
3921                         Con_DPrintf("from disk %s... ", filename);
3922                 return shaderstring;
3923         }
3924         return shaderstring;
3925 }
3926
3927 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3928 {
3929         // TODO: load or create .fp and .vp shader files
3930 }
3931
3932 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3933 {
3934         int i;
3935         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3936         int vertstrings_count = 0, vertstring_length = 0;
3937         int geomstrings_count = 0, geomstring_length = 0;
3938         int fragstrings_count = 0, fragstring_length = 0;
3939         char *t;
3940         char *vertexstring, *geometrystring, *fragmentstring;
3941         char *vertstring, *geomstring, *fragstring;
3942         const char *vertstrings_list[32+3];
3943         const char *geomstrings_list[32+3];
3944         const char *fragstrings_list[32+3];
3945         char permutationname[256];
3946         char cachename[256];
3947         CGprofile vertexProfile;
3948         CGprofile fragmentProfile;
3949
3950         if (p->compiled)
3951                 return;
3952         p->compiled = true;
3953         p->vprogram = NULL;
3954         p->fprogram = NULL;
3955
3956         permutationname[0] = 0;
3957         cachename[0] = 0;
3958         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3959         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3960         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3961
3962         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3963         strlcat(cachename, "cg/", sizeof(cachename));
3964
3965         // the first pretext is which type of shader to compile as
3966         // (later these will all be bound together as a program object)
3967         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3968         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3969         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3970
3971         // the second pretext is the mode (for example a light source)
3972         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3973         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3974         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3975         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3976         strlcat(cachename, modeinfo->name, sizeof(cachename));
3977
3978         // now add all the permutation pretexts
3979         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3980         {
3981                 if (permutation & (1<<i))
3982                 {
3983                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3984                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3985                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3986                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3987                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3988                 }
3989                 else
3990                 {
3991                         // keep line numbers correct
3992                         vertstrings_list[vertstrings_count++] = "\n";
3993                         geomstrings_list[geomstrings_count++] = "\n";
3994                         fragstrings_list[fragstrings_count++] = "\n";
3995                 }
3996         }
3997
3998         // replace spaces in the cachename with _ characters
3999         for (i = 0;cachename[i];i++)
4000                 if (cachename[i] == ' ')
4001                         cachename[i] = '_';
4002
4003         // now append the shader text itself
4004         vertstrings_list[vertstrings_count++] = vertexstring;
4005         geomstrings_list[geomstrings_count++] = geometrystring;
4006         fragstrings_list[fragstrings_count++] = fragmentstring;
4007
4008         // if any sources were NULL, clear the respective list
4009         if (!vertexstring)
4010                 vertstrings_count = 0;
4011         if (!geometrystring)
4012                 geomstrings_count = 0;
4013         if (!fragmentstring)
4014                 fragstrings_count = 0;
4015
4016         vertstring_length = 0;
4017         for (i = 0;i < vertstrings_count;i++)
4018                 vertstring_length += strlen(vertstrings_list[i]);
4019         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4020         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4021                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4022
4023         geomstring_length = 0;
4024         for (i = 0;i < geomstrings_count;i++)
4025                 geomstring_length += strlen(geomstrings_list[i]);
4026         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4027         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4028                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4029
4030         fragstring_length = 0;
4031         for (i = 0;i < fragstrings_count;i++)
4032                 fragstring_length += strlen(fragstrings_list[i]);
4033         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4034         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4035                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4036
4037         CHECKGLERROR
4038         CHECKCGERROR
4039         //vertexProfile = CG_PROFILE_ARBVP1;
4040         //fragmentProfile = CG_PROFILE_ARBFP1;
4041         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4042         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4043         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4044         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4045         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4046         CHECKGLERROR
4047
4048         // try to load the cached shader, or generate one
4049         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4050
4051         // if caching failed, do a dynamic compile for now
4052         CHECKCGERROR
4053         if (vertstring[0] && !p->vprogram)
4054                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4055         CHECKCGERROR
4056         if (fragstring[0] && !p->fprogram)
4057                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4058         CHECKCGERROR
4059
4060         // look up all the uniform variable names we care about, so we don't
4061         // have to look them up every time we set them
4062         if (p->vprogram)
4063         {
4064                 CHECKCGERROR
4065                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4066                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4067                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4068                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4069                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4070                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4071                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4072                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4073                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4074                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4075                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4076                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4077                 CHECKCGERROR
4078         }
4079         if (p->fprogram)
4080         {
4081                 CHECKCGERROR
4082                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4083                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4084                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4085                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4086                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4087                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4088                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4089                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4090                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4091                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4092                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4093                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4094                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4095                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4096                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4097                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4098                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4099                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4100                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4101                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4102                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4103                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4104                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4105                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4106                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4107                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4108                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4109                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4110                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4111                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4112                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4113                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4114                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4115                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4116                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4117                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4118                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4119                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4120                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4121                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4122                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4123                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4124                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4125                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4126                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4127                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4128                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4129                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4130                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4131                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4132                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4133                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4134                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4135                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4136                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4137                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4138                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4139                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4140                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4141                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4142                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4143                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4144                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4145                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4146                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4147                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4148                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4149                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4150                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4151                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4152                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4153                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4154                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4155                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4156                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4157                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4158                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4159                 CHECKCGERROR
4160         }
4161
4162         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4163                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4164         else
4165                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4166
4167         // free the strings
4168         if (vertstring)
4169                 Mem_Free(vertstring);
4170         if (geomstring)
4171                 Mem_Free(geomstring);
4172         if (fragstring)
4173                 Mem_Free(fragstring);
4174         if (vertexstring)
4175                 Mem_Free(vertexstring);
4176         if (geometrystring)
4177                 Mem_Free(geometrystring);
4178         if (fragmentstring)
4179                 Mem_Free(fragmentstring);
4180 }
4181
4182 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4183 {
4184         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4185         CHECKGLERROR
4186         CHECKCGERROR
4187         if (r_cg_permutation != perm)
4188         {
4189                 r_cg_permutation = perm;
4190                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4191                 {
4192                         if (!r_cg_permutation->compiled)
4193                                 R_CG_CompilePermutation(perm, mode, permutation);
4194                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4195                         {
4196                                 // remove features until we find a valid permutation
4197                                 int i;
4198                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4199                                 {
4200                                         // reduce i more quickly whenever it would not remove any bits
4201                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4202                                         if (!(permutation & j))
4203                                                 continue;
4204                                         permutation -= j;
4205                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4206                                         if (!r_cg_permutation->compiled)
4207                                                 R_CG_CompilePermutation(perm, mode, permutation);
4208                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4209                                                 break;
4210                                 }
4211                                 if (i >= SHADERPERMUTATION_COUNT)
4212                                 {
4213                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4214                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4215                                         return; // no bit left to clear, entire mode is broken
4216                                 }
4217                         }
4218                 }
4219                 CHECKGLERROR
4220                 CHECKCGERROR
4221                 if (r_cg_permutation->vprogram)
4222                 {
4223                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4224                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4225                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4226                 }
4227                 else
4228                 {
4229                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4230                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4231                 }
4232                 if (r_cg_permutation->fprogram)
4233                 {
4234                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4235                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4236                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4237                 }
4238                 else
4239                 {
4240                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4241                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4242                 }
4243         }
4244         CHECKCGERROR
4245         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4246         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4247         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4248 }
4249
4250 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4251 {
4252         cgGLSetTextureParameter(param, R_GetTexture(tex));
4253         cgGLEnableTextureParameter(param);
4254 }
4255 #endif
4256
4257 void R_GLSL_Restart_f(void)
4258 {
4259         unsigned int i, limit;
4260         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4261                 Mem_Free(glslshaderstring);
4262         glslshaderstring = NULL;
4263         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4264                 Mem_Free(cgshaderstring);
4265         cgshaderstring = NULL;
4266         switch(vid.renderpath)
4267         {
4268         case RENDERPATH_GL20:
4269                 {
4270                         r_glsl_permutation_t *p;
4271                         r_glsl_permutation = NULL;
4272                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4273                         for (i = 0;i < limit;i++)
4274                         {
4275                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4276                                 {
4277                                         GL_Backend_FreeProgram(p->program);
4278                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4279                                 }
4280                         }
4281                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4282                 }
4283                 break;
4284         case RENDERPATH_CGGL:
4285 #ifdef SUPPORTCG
4286                 {
4287                         r_cg_permutation_t *p;
4288                         r_cg_permutation = NULL;
4289                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4290                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4291                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4292                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4293                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4294                         for (i = 0;i < limit;i++)
4295                         {
4296                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4297                                 {
4298                                         if (p->vprogram)
4299                                                 cgDestroyProgram(p->vprogram);
4300                                         if (p->fprogram)
4301                                                 cgDestroyProgram(p->fprogram);
4302                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4303                                 }
4304                         }
4305                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4306                 }
4307                 break;
4308 #endif
4309         case RENDERPATH_GL13:
4310         case RENDERPATH_GL11:
4311                 break;
4312         }
4313 }
4314
4315 void R_GLSL_DumpShader_f(void)
4316 {
4317         int i;
4318         qfile_t *file;
4319
4320         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4321         if (file)
4322         {
4323                 FS_Print(file, "/* The engine may define the following macros:\n");
4324                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4325                 for (i = 0;i < SHADERMODE_COUNT;i++)
4326                         FS_Print(file, glslshadermodeinfo[i].pretext);
4327                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4328                         FS_Print(file, shaderpermutationinfo[i].pretext);
4329                 FS_Print(file, "*/\n");
4330                 FS_Print(file, builtinshaderstring);
4331                 FS_Close(file);
4332                 Con_Printf("glsl/default.glsl written\n");
4333         }
4334         else
4335                 Con_Printf("failed to write to glsl/default.glsl\n");
4336
4337 #ifdef SUPPORTCG
4338         file = FS_OpenRealFile("cg/default.cg", "w", false);
4339         if (file)
4340         {
4341                 FS_Print(file, "/* The engine may define the following macros:\n");
4342                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4343                 for (i = 0;i < SHADERMODE_COUNT;i++)
4344                         FS_Print(file, cgshadermodeinfo[i].pretext);
4345                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4346                         FS_Print(file, shaderpermutationinfo[i].pretext);
4347                 FS_Print(file, "*/\n");
4348                 FS_Print(file, builtincgshaderstring);
4349                 FS_Close(file);
4350                 Con_Printf("cg/default.cg written\n");
4351         }
4352         else
4353                 Con_Printf("failed to write to cg/default.cg\n");
4354 #endif
4355 }
4356
4357 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4358 {
4359         if (!second)
4360                 texturemode = GL_MODULATE;
4361         switch (vid.renderpath)
4362         {
4363         case RENDERPATH_GL20:
4364                 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))));
4365                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4366                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4367                 break;
4368         case RENDERPATH_CGGL:
4369 #ifdef SUPPORTCG
4370                 CHECKCGERROR
4371                 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))));
4372                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4373                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4374 #endif
4375                 break;
4376         case RENDERPATH_GL13:
4377                 R_Mesh_TexBind(0, first );
4378                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4379                 R_Mesh_TexBind(1, second);
4380                 if (second)
4381                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4382                 break;
4383         case RENDERPATH_GL11:
4384                 R_Mesh_TexBind(0, first );
4385                 break;
4386         }
4387 }
4388
4389 void R_SetupShader_DepthOrShadow(void)
4390 {
4391         switch (vid.renderpath)
4392         {
4393         case RENDERPATH_GL20:
4394                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4395                 break;
4396         case RENDERPATH_CGGL:
4397 #ifdef SUPPORTCG
4398                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4399 #endif
4400                 break;
4401         case RENDERPATH_GL13:
4402                 R_Mesh_TexBind(0, 0);
4403                 R_Mesh_TexBind(1, 0);
4404                 break;
4405         case RENDERPATH_GL11:
4406                 R_Mesh_TexBind(0, 0);
4407                 break;
4408         }
4409 }
4410
4411 void R_SetupShader_ShowDepth(void)
4412 {
4413         switch (vid.renderpath)
4414         {
4415         case RENDERPATH_GL20:
4416                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4417                 break;
4418         case RENDERPATH_CGGL:
4419 #ifdef SUPPORTCG
4420                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4421 #endif
4422                 break;
4423         case RENDERPATH_GL13:
4424                 break;
4425         case RENDERPATH_GL11:
4426                 break;
4427         }
4428 }
4429
4430 extern qboolean r_shadow_usingdeferredprepass;
4431 extern cvar_t r_shadow_deferred_8bitrange;
4432 extern rtexture_t *r_shadow_attenuationgradienttexture;
4433 extern rtexture_t *r_shadow_attenuation2dtexture;
4434 extern rtexture_t *r_shadow_attenuation3dtexture;
4435 extern qboolean r_shadow_usingshadowmaprect;
4436 extern qboolean r_shadow_usingshadowmapcube;
4437 extern qboolean r_shadow_usingshadowmap2d;
4438 extern qboolean r_shadow_usingshadowmaportho;
4439 extern float r_shadow_shadowmap_texturescale[2];
4440 extern float r_shadow_shadowmap_parameters[4];
4441 extern qboolean r_shadow_shadowmapvsdct;
4442 extern qboolean r_shadow_shadowmapsampler;
4443 extern int r_shadow_shadowmappcf;
4444 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4445 extern rtexture_t *r_shadow_shadowmap2dtexture;
4446 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4447 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4448 extern matrix4x4_t r_shadow_shadowmapmatrix;
4449 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4450 extern int r_shadow_prepass_width;
4451 extern int r_shadow_prepass_height;
4452 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4453 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4454 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4455 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4456 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4457 {
4458         // select a permutation of the lighting shader appropriate to this
4459         // combination of texture, entity, light source, and fogging, only use the
4460         // minimum features necessary to avoid wasting rendering time in the
4461         // fragment shader on features that are not being used
4462         unsigned int permutation = 0;
4463         unsigned int mode = 0;
4464         float m16f[16];
4465         if (rsurfacepass == RSURFPASS_BACKGROUND)
4466         {
4467                 // distorted background
4468                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4469                         mode = SHADERMODE_WATER;
4470                 else
4471                         mode = SHADERMODE_REFRACTION;
4472                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4473                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4474                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4475                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4476                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4477                 R_Mesh_ColorPointer(NULL, 0, 0);
4478                 GL_AlphaTest(false);
4479                 GL_BlendFunc(GL_ONE, GL_ZERO);
4480         }
4481         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4482         {
4483                 if (r_glsl_offsetmapping.integer)
4484                 {
4485                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4486                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4487                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4488                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4489                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4490                         {
4491                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4492                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4493                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4494                         }
4495                 }
4496                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4497                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4498                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4499                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4500                 // normalmap (deferred prepass), may use alpha test on diffuse
4501                 mode = SHADERMODE_DEFERREDGEOMETRY;
4502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4503                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4504                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4505                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4506                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4507                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4508                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4509                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4510                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4511                 else
4512                         R_Mesh_ColorPointer(NULL, 0, 0);
4513                 GL_AlphaTest(false);
4514                 GL_BlendFunc(GL_ONE, GL_ZERO);
4515         }
4516         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4517         {
4518                 if (r_glsl_offsetmapping.integer)
4519                 {
4520                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4521                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4522                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4523                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4524                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4525                         {
4526                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4527                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4528                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4529                         }
4530                 }
4531                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4532                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4533                 // light source
4534                 mode = SHADERMODE_LIGHTSOURCE;
4535                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4536                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4537                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4538                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4539                 if (diffusescale > 0)
4540                         permutation |= SHADERPERMUTATION_DIFFUSE;
4541                 if (specularscale > 0)
4542                 {
4543                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4544                         if (r_shadow_glossexact.integer)
4545                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4546                 }
4547                 if (r_refdef.fogenabled)
4548                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4549                 if (rsurface.texture->colormapping)
4550                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4551                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4552                 {
4553                         if (r_shadow_usingshadowmaprect)
4554                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4555                         if (r_shadow_usingshadowmap2d)
4556                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4557                         if (r_shadow_usingshadowmapcube)
4558                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4559                         else if(r_shadow_shadowmapvsdct)
4560                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4561
4562                         if (r_shadow_shadowmapsampler)
4563                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4564                         if (r_shadow_shadowmappcf > 1)
4565                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4566                         else if (r_shadow_shadowmappcf)
4567                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4568                 }
4569                 if (rsurface.texture->reflectmasktexture)
4570                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4571                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4572                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4573                 {
4574                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4575                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4576                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4577                 }
4578                 else
4579                 {
4580                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4581                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4582                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4583                 }
4584                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4585                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4586                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4587                 else
4588                         R_Mesh_ColorPointer(NULL, 0, 0);
4589                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4590                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4591         }
4592         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4593         {
4594                 if (r_glsl_offsetmapping.integer)
4595                 {
4596                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4597                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4598                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4599                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4600                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4601                         {
4602                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4603                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4604                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4605                         }
4606                 }
4607                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4608                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4609                 // unshaded geometry (fullbright or ambient model lighting)
4610                 mode = SHADERMODE_FLATCOLOR;
4611                 ambientscale = diffusescale = specularscale = 0;
4612                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4613                         permutation |= SHADERPERMUTATION_GLOW;
4614                 if (r_refdef.fogenabled)
4615                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4616                 if (rsurface.texture->colormapping)
4617                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4618                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4619                 {
4620                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4621                         if (r_shadow_usingshadowmaprect)
4622                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4623                         if (r_shadow_usingshadowmap2d)
4624                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4625
4626                         if (r_shadow_shadowmapsampler)
4627                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4628                         if (r_shadow_shadowmappcf > 1)
4629                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4630                         else if (r_shadow_shadowmappcf)
4631                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4632                 }
4633                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4634                         permutation |= SHADERPERMUTATION_REFLECTION;
4635                 if (rsurface.texture->reflectmasktexture)
4636                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4637                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4638                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4639                 {
4640                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4641                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4642                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4643                 }
4644                 else
4645                 {
4646                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4647                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4648                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4649                 }
4650                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4651                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4652                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4653                 else
4654                         R_Mesh_ColorPointer(NULL, 0, 0);
4655                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4656                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4657         }
4658         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4659         {
4660                 if (r_glsl_offsetmapping.integer)
4661                 {
4662                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4663                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4664                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4665                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4666                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4667                         {
4668                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4669                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4670                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4671                         }
4672                 }
4673                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4674                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4675                 // directional model lighting
4676                 mode = SHADERMODE_LIGHTDIRECTION;
4677                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4678                         permutation |= SHADERPERMUTATION_GLOW;
4679                 permutation |= SHADERPERMUTATION_DIFFUSE;
4680                 if (specularscale > 0)
4681                 {
4682                         permutation |= SHADERPERMUTATION_SPECULAR;
4683                         if (r_shadow_glossexact.integer)
4684                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4685                 }
4686                 if (r_refdef.fogenabled)
4687                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4688                 if (rsurface.texture->colormapping)
4689                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4690                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4691                 {
4692                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4693                         if (r_shadow_usingshadowmaprect)
4694                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4695                         if (r_shadow_usingshadowmap2d)
4696                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4697
4698                         if (r_shadow_shadowmapsampler)
4699                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4700                         if (r_shadow_shadowmappcf > 1)
4701                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4702                         else if (r_shadow_shadowmappcf)
4703                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4704                 }
4705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4706                         permutation |= SHADERPERMUTATION_REFLECTION;
4707                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4708                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4709                 if (rsurface.texture->reflectmasktexture)
4710                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4711                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4712                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4713                 {
4714                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4715                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4716                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4717                 }
4718                 else
4719                 {
4720                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4721                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4722                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4723                 }
4724                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4725                 R_Mesh_ColorPointer(NULL, 0, 0);
4726                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4727                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4728         }
4729         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4730         {
4731                 if (r_glsl_offsetmapping.integer)
4732                 {
4733                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4734                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4735                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4736                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4737                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4738                         {
4739                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4740                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4741                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4742                         }
4743                 }
4744                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4745                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4746                 // ambient model lighting
4747                 mode = SHADERMODE_LIGHTDIRECTION;
4748                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4749                         permutation |= SHADERPERMUTATION_GLOW;
4750                 if (r_refdef.fogenabled)
4751                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4752                 if (rsurface.texture->colormapping)
4753                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4754                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4755                 {
4756                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4757                         if (r_shadow_usingshadowmaprect)
4758                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4759                         if (r_shadow_usingshadowmap2d)
4760                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4761
4762                         if (r_shadow_shadowmapsampler)
4763                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4764                         if (r_shadow_shadowmappcf > 1)
4765                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4766                         else if (r_shadow_shadowmappcf)
4767                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4768                 }
4769                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4770                         permutation |= SHADERPERMUTATION_REFLECTION;
4771                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4772                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4773                 if (rsurface.texture->reflectmasktexture)
4774                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4775                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4776                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4777                 {
4778                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4779                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4780                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4781                 }
4782                 else
4783                 {
4784                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4785                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4786                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4787                 }
4788                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4789                 R_Mesh_ColorPointer(NULL, 0, 0);
4790                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4791                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4792         }
4793         else
4794         {
4795                 if (r_glsl_offsetmapping.integer)
4796                 {
4797                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4798                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4799                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4800                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4801                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4802                         {
4803                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4804                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4805                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4806                         }
4807                 }
4808                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4809                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4810                 // lightmapped wall
4811                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4812                         permutation |= SHADERPERMUTATION_GLOW;
4813                 if (r_refdef.fogenabled)
4814                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4815                 if (rsurface.texture->colormapping)
4816                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4817                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4818                 {
4819                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4820                         if (r_shadow_usingshadowmaprect)
4821                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4822                         if (r_shadow_usingshadowmap2d)
4823                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4824
4825                         if (r_shadow_shadowmapsampler)
4826                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4827                         if (r_shadow_shadowmappcf > 1)
4828                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4829                         else if (r_shadow_shadowmappcf)
4830                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4831                 }
4832                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4833                         permutation |= SHADERPERMUTATION_REFLECTION;
4834                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4835                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4836                 if (rsurface.texture->reflectmasktexture)
4837                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4838                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4839                 {
4840                         // deluxemapping (light direction texture)
4841                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4842                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4843                         else
4844                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4845                         permutation |= SHADERPERMUTATION_DIFFUSE;
4846                         if (specularscale > 0)
4847                         {
4848                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4849                                 if (r_shadow_glossexact.integer)
4850                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4851                         }
4852                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4853                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4854                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4855                         else
4856                                 R_Mesh_ColorPointer(NULL, 0, 0);
4857                 }
4858                 else if (r_glsl_deluxemapping.integer >= 2)
4859                 {
4860                         // fake deluxemapping (uniform light direction in tangentspace)
4861                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4862                         permutation |= SHADERPERMUTATION_DIFFUSE;
4863                         if (specularscale > 0)
4864                         {
4865                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4866                                 if (r_shadow_glossexact.integer)
4867                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4868                         }
4869                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4870                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4871                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4872                         else
4873                                 R_Mesh_ColorPointer(NULL, 0, 0);
4874                 }
4875                 else if (rsurface.uselightmaptexture)
4876                 {
4877                         // ordinary lightmapping (q1bsp, q3bsp)
4878                         mode = SHADERMODE_LIGHTMAP;
4879                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4880                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4881                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4882                         else
4883                                 R_Mesh_ColorPointer(NULL, 0, 0);
4884                 }
4885                 else
4886                 {
4887                         // ordinary vertex coloring (q3bsp)
4888                         mode = SHADERMODE_VERTEXCOLOR;
4889                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4890                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4891                 }
4892                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4893                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4894                 {
4895                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4896                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4897                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4898                 }
4899                 else
4900                 {
4901                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4902                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4903                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4904                 }
4905                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4906                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4907         }
4908         switch(vid.renderpath)
4909         {
4910         case RENDERPATH_GL20:
4911                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4912                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4913                 if (mode == SHADERMODE_LIGHTSOURCE)
4914                 {
4915                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4916                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4917                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4918                         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);
4919                         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);
4920                         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);
4921         
4922                         // additive passes are only darkened by fog, not tinted
4923                         if (r_glsl_permutation->loc_FogColor >= 0)
4924                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4925                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4926                 }
4927                 else
4928                 {
4929                         if (mode == SHADERMODE_FLATCOLOR)
4930                         {
4931                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4932                         }
4933                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4934                         {
4935                                 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]);
4936                                 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]);
4937                                 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);
4938                                 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);
4939                                 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);
4940                                 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]);
4941                                 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]);
4942                         }
4943                         else
4944                         {
4945                                 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]);
4946                                 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]);
4947                                 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);
4948                                 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);
4949                                 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);
4950                         }
4951                         // additive passes are only darkened by fog, not tinted
4952                         if (r_glsl_permutation->loc_FogColor >= 0)
4953                         {
4954                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4955                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4956                                 else
4957                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4958                         }
4959                         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);
4960                         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]);
4961                         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]);
4962                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4963                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4964                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4965                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4966                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4967                 }
4968                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4969                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4970                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4971                 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]);
4972                 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]);
4973
4974                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4975                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4976                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4977                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4978                 {
4979                         if (rsurface.texture->pantstexture)
4980                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4981                         else
4982                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4983                 }
4984                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4985                 {
4986                         if (rsurface.texture->shirttexture)
4987                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4988                         else
4989                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4990                 }
4991                 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]);
4992                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4993                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4994                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4995                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
4996                 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]);
4997                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4998
4999         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5000         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5001         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5002                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5003                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5004                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5005                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5006                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5007                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5008                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5009                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5010                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5011                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5012                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5013                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5014                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5015                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5016                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5017                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5018                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5019                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5020                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5021                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5022                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5023                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5024                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5025                 {
5026                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5027                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5028                         if (rsurface.rtlight)
5029                         {
5030                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5031                                 if (r_shadow_usingshadowmapcube)
5032                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5033                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5034                         }
5035                 }
5036                 CHECKGLERROR
5037                 break;
5038         case RENDERPATH_CGGL:
5039 #ifdef SUPPORTCG
5040                 R_SetupShader_SetPermutationCG(mode, permutation);
5041                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5042                 if (mode == SHADERMODE_LIGHTSOURCE)
5043                 {
5044                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5045                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5046                 }
5047                 else
5048                 {
5049                         if (mode == SHADERMODE_LIGHTDIRECTION)
5050                         {
5051                                 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
5052                         }
5053                 }
5054                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5055                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5056                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5057                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5058                 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
5059                 CHECKGLERROR
5060
5061                 if (mode == SHADERMODE_LIGHTSOURCE)
5062                 {
5063                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5064                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5065                         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
5066                         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
5067                         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
5068
5069                         // additive passes are only darkened by fog, not tinted
5070                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5071                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5072                 }
5073                 else
5074                 {
5075                         if (mode == SHADERMODE_FLATCOLOR)
5076                         {
5077                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5078                         }
5079                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5080                         {
5081                                 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
5082                                 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
5083                                 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
5084                                 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
5085                                 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
5086                                 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
5087                                 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
5088                         }
5089                         else
5090                         {
5091                                 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
5092                                 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
5093                                 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
5094                                 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
5095                                 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
5096                         }
5097                         // additive passes are only darkened by fog, not tinted
5098                         if (r_cg_permutation->fp_FogColor)
5099                         {
5100                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5101                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5102                                 else
5103                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5104                                 CHECKCGERROR
5105                         }
5106                         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
5107                         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
5108                         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
5109                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5110                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5111                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5112                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5113                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5114                 }
5115                 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
5116                 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
5117                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5118                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5119                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5120                 if (r_cg_permutation->fp_Color_Pants)
5121                 {
5122                         if (rsurface.texture->pantstexture)
5123                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5124                         else
5125                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5126                         CHECKCGERROR
5127                 }
5128                 if (r_cg_permutation->fp_Color_Shirt)
5129                 {
5130                         if (rsurface.texture->shirttexture)
5131                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5132                         else
5133                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5134                         CHECKCGERROR
5135                 }
5136                 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
5137                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5138                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5139                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5140                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5141                 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
5142                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5143
5144         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5145         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5146         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5147                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5148                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5149                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5150                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5151                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5152                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5153                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5154                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5155                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5156                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5157                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5158                 if (r_cg_permutation->fp_Texture_ReflectCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectCube    , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);CHECKCGERROR
5159                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5160                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5161                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5162                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5163                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5164                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5165                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5166                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5167                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5168                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5169                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5170                 {
5171                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5172                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5173                         if (rsurface.rtlight)
5174                         {
5175                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5176                                 if (r_shadow_usingshadowmapcube)
5177                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5178                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5179                         }
5180                 }
5181
5182                 CHECKGLERROR
5183 #endif
5184                 break;
5185         case RENDERPATH_GL13:
5186         case RENDERPATH_GL11:
5187                 break;
5188         }
5189 }
5190
5191 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5192 {
5193         // select a permutation of the lighting shader appropriate to this
5194         // combination of texture, entity, light source, and fogging, only use the
5195         // minimum features necessary to avoid wasting rendering time in the
5196         // fragment shader on features that are not being used
5197         unsigned int permutation = 0;
5198         unsigned int mode = 0;
5199         const float *lightcolorbase = rtlight->currentcolor;
5200         float ambientscale = rtlight->ambientscale;
5201         float diffusescale = rtlight->diffusescale;
5202         float specularscale = rtlight->specularscale;
5203         // this is the location of the light in view space
5204         vec3_t viewlightorigin;
5205         // this transforms from view space (camera) to light space (cubemap)
5206         matrix4x4_t viewtolight;
5207         matrix4x4_t lighttoview;
5208         float viewtolight16f[16];
5209         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5210         // light source
5211         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5212         if (rtlight->currentcubemap != r_texture_whitecube)
5213                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5214         if (diffusescale > 0)
5215                 permutation |= SHADERPERMUTATION_DIFFUSE;
5216         if (specularscale > 0)
5217         {
5218                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5219                 if (r_shadow_glossexact.integer)
5220                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5221         }
5222         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5223         {
5224                 if (r_shadow_usingshadowmaprect)
5225                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5226                 if (r_shadow_usingshadowmap2d)
5227                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5228                 if (r_shadow_usingshadowmapcube)
5229                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5230                 else if(r_shadow_shadowmapvsdct)
5231                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5232
5233                 if (r_shadow_shadowmapsampler)
5234                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5235                 if (r_shadow_shadowmappcf > 1)
5236                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5237                 else if (r_shadow_shadowmappcf)
5238                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5239         }
5240         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5241         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5242         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5243         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5244         switch(vid.renderpath)
5245         {
5246         case RENDERPATH_GL20:
5247                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5248                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5249                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5250                 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);
5251                 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);
5252                 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);
5253                 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]);
5254                 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]);
5255                 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));
5256                 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]);
5257                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5258
5259                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5260                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5261                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5262                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5263                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5264                 if (r_shadow_usingshadowmapcube)
5265                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5266                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5267                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5268                 break;
5269         case RENDERPATH_CGGL:
5270 #ifdef SUPPORTCG
5271                 R_SetupShader_SetPermutationCG(mode, permutation);
5272                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5273                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5274                 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
5275                 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
5276                 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
5277                 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
5278                 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
5279                 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
5280                 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
5281                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5282
5283                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5284                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5285                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5286                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5287                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5288                 if (r_shadow_usingshadowmapcube)
5289                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5290                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5291                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5292 #endif
5293                 break;
5294         case RENDERPATH_GL13:
5295         case RENDERPATH_GL11:
5296                 break;
5297         }
5298 }
5299
5300 #define SKINFRAME_HASH 1024
5301
5302 typedef struct
5303 {
5304         int loadsequence; // incremented each level change
5305         memexpandablearray_t array;
5306         skinframe_t *hash[SKINFRAME_HASH];
5307 }
5308 r_skinframe_t;
5309 r_skinframe_t r_skinframe;
5310
5311 void R_SkinFrame_PrepareForPurge(void)
5312 {
5313         r_skinframe.loadsequence++;
5314         // wrap it without hitting zero
5315         if (r_skinframe.loadsequence >= 200)
5316                 r_skinframe.loadsequence = 1;
5317 }
5318
5319 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5320 {
5321         if (!skinframe)
5322                 return;
5323         // mark the skinframe as used for the purging code
5324         skinframe->loadsequence = r_skinframe.loadsequence;
5325 }
5326
5327 void R_SkinFrame_Purge(void)
5328 {
5329         int i;
5330         skinframe_t *s;
5331         for (i = 0;i < SKINFRAME_HASH;i++)
5332         {
5333                 for (s = r_skinframe.hash[i];s;s = s->next)
5334                 {
5335                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5336                         {
5337                                 if (s->merged == s->base)
5338                                         s->merged = NULL;
5339                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5340                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5341                                 R_PurgeTexture(s->merged);s->merged = NULL;
5342                                 R_PurgeTexture(s->base  );s->base   = NULL;
5343                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5344                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5345                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5346                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5347                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5348                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5349                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5350                                 s->loadsequence = 0;
5351                         }
5352                 }
5353         }
5354 }
5355
5356 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5357         skinframe_t *item;
5358         char basename[MAX_QPATH];
5359
5360         Image_StripImageExtension(name, basename, sizeof(basename));
5361
5362         if( last == NULL ) {
5363                 int hashindex;
5364                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5365                 item = r_skinframe.hash[hashindex];
5366         } else {
5367                 item = last->next;
5368         }
5369
5370         // linearly search through the hash bucket
5371         for( ; item ; item = item->next ) {
5372                 if( !strcmp( item->basename, basename ) ) {
5373                         return item;
5374                 }
5375         }
5376         return NULL;
5377 }
5378
5379 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5380 {
5381         skinframe_t *item;
5382         int hashindex;
5383         char basename[MAX_QPATH];
5384
5385         Image_StripImageExtension(name, basename, sizeof(basename));
5386
5387         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5388         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5389                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5390                         break;
5391
5392         if (!item) {
5393                 rtexture_t *dyntexture;
5394                 // check whether its a dynamic texture
5395                 dyntexture = CL_GetDynTexture( basename );
5396                 if (!add && !dyntexture)
5397                         return NULL;
5398                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5399                 memset(item, 0, sizeof(*item));
5400                 strlcpy(item->basename, basename, sizeof(item->basename));
5401                 item->base = dyntexture; // either NULL or dyntexture handle
5402                 item->textureflags = textureflags;
5403                 item->comparewidth = comparewidth;
5404                 item->compareheight = compareheight;
5405                 item->comparecrc = comparecrc;
5406                 item->next = r_skinframe.hash[hashindex];
5407                 r_skinframe.hash[hashindex] = item;
5408         }
5409         else if( item->base == NULL )
5410         {
5411                 rtexture_t *dyntexture;
5412                 // check whether its a dynamic texture
5413                 // 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]
5414                 dyntexture = CL_GetDynTexture( basename );
5415                 item->base = dyntexture; // either NULL or dyntexture handle
5416         }
5417
5418         R_SkinFrame_MarkUsed(item);
5419         return item;
5420 }
5421
5422 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5423         { \
5424                 unsigned long long avgcolor[5], wsum; \
5425                 int pix, comp, w; \
5426                 avgcolor[0] = 0; \
5427                 avgcolor[1] = 0; \
5428                 avgcolor[2] = 0; \
5429                 avgcolor[3] = 0; \
5430                 avgcolor[4] = 0; \
5431                 wsum = 0; \
5432                 for(pix = 0; pix < cnt; ++pix) \
5433                 { \
5434                         w = 0; \
5435                         for(comp = 0; comp < 3; ++comp) \
5436                                 w += getpixel; \
5437                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5438                         { \
5439                                 ++wsum; \
5440                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5441                                 w = getpixel; \
5442                                 for(comp = 0; comp < 3; ++comp) \
5443                                         avgcolor[comp] += getpixel * w; \
5444                                 avgcolor[3] += w; \
5445                         } \
5446                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5447                         avgcolor[4] += getpixel; \
5448                 } \
5449                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5450                         avgcolor[3] = 1; \
5451                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5452                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5453                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5454                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5455         }
5456
5457 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5458 {
5459         int j;
5460         unsigned char *pixels;
5461         unsigned char *bumppixels;
5462         unsigned char *basepixels = NULL;
5463         int basepixels_width = 0;
5464         int basepixels_height = 0;
5465         skinframe_t *skinframe;
5466         rtexture_t *ddsbase = NULL;
5467         qboolean ddshasalpha = false;
5468         float ddsavgcolor[4];
5469         char basename[MAX_QPATH];
5470
5471         if (cls.state == ca_dedicated)
5472                 return NULL;
5473
5474         // return an existing skinframe if already loaded
5475         // if loading of the first image fails, don't make a new skinframe as it
5476         // would cause all future lookups of this to be missing
5477         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5478         if (skinframe && skinframe->base)
5479                 return skinframe;
5480
5481         Image_StripImageExtension(name, basename, sizeof(basename));
5482
5483         // check for DDS texture file first
5484         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5485         {
5486                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5487                 if (basepixels == NULL)
5488                         return NULL;
5489         }
5490
5491         if (developer_loading.integer)
5492                 Con_Printf("loading skin \"%s\"\n", name);
5493
5494         // we've got some pixels to store, so really allocate this new texture now
5495         if (!skinframe)
5496                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5497         skinframe->stain = NULL;
5498         skinframe->merged = NULL;
5499         skinframe->base = NULL;
5500         skinframe->pants = NULL;
5501         skinframe->shirt = NULL;
5502         skinframe->nmap = NULL;
5503         skinframe->gloss = NULL;
5504         skinframe->glow = NULL;
5505         skinframe->fog = NULL;
5506         skinframe->reflect = NULL;
5507         skinframe->hasalpha = false;
5508
5509         if (ddsbase)
5510         {
5511                 skinframe->base = ddsbase;
5512                 skinframe->hasalpha = ddshasalpha;
5513                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5514                 if (r_loadfog && skinframe->hasalpha)
5515                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5516                 //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]);
5517         }
5518         else
5519         {
5520                 basepixels_width = image_width;
5521                 basepixels_height = image_height;
5522                 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);
5523                 if (textureflags & TEXF_ALPHA)
5524                 {
5525                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5526                         {
5527                                 if (basepixels[j] < 255)
5528                                 {
5529                                         skinframe->hasalpha = true;
5530                                         break;
5531                                 }
5532                         }
5533                         if (r_loadfog && skinframe->hasalpha)
5534                         {
5535                                 // has transparent pixels
5536                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5537                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5538                                 {
5539                                         pixels[j+0] = 255;
5540                                         pixels[j+1] = 255;
5541                                         pixels[j+2] = 255;
5542                                         pixels[j+3] = basepixels[j+3];
5543                                 }
5544                                 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);
5545                                 Mem_Free(pixels);
5546                         }
5547                 }
5548                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5549                 //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]);
5550                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5551                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5552                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5553                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5554         }
5555
5556         if (r_loaddds)
5557         {
5558                 if (r_loadnormalmap)
5559                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5560                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5561                 if (r_loadgloss)
5562                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5563                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5564                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5565                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5566         }
5567
5568         // _norm is the name used by tenebrae and has been adopted as standard
5569         if (r_loadnormalmap && skinframe->nmap == NULL)
5570         {
5571                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5572                 {
5573                         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);
5574                         Mem_Free(pixels);
5575                         pixels = NULL;
5576                 }
5577                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5578                 {
5579                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5580                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5581                         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);
5582                         Mem_Free(pixels);
5583                         Mem_Free(bumppixels);
5584                 }
5585                 else if (r_shadow_bumpscale_basetexture.value > 0)
5586                 {
5587                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5588                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5589                         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);
5590                         Mem_Free(pixels);
5591                 }
5592                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5593                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5594         }
5595
5596         // _luma is supported only for tenebrae compatibility
5597         // _glow is the preferred name
5598         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer))))
5599         {
5600                 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);
5601                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5602                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5603                 Mem_Free(pixels);pixels = NULL;
5604         }
5605
5606         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5607         {
5608                 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);
5609                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5610                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5611                 Mem_Free(pixels);
5612                 pixels = NULL;
5613         }
5614
5615         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5616         {
5617                 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);
5618                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5619                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5620                 Mem_Free(pixels);
5621                 pixels = NULL;
5622         }
5623
5624         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5625         {
5626                 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);
5627                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5628                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5629                 Mem_Free(pixels);
5630                 pixels = NULL;
5631         }
5632
5633         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5634         {
5635                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, skinframe->textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), NULL);
5636                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5637                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5638                 Mem_Free(pixels);
5639                 pixels = NULL;
5640         }
5641
5642         if (basepixels)
5643                 Mem_Free(basepixels);
5644
5645         return skinframe;
5646 }
5647
5648 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5649 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5650 {
5651         int i;
5652         unsigned char *temp1, *temp2;
5653         skinframe_t *skinframe;
5654
5655         if (cls.state == ca_dedicated)
5656                 return NULL;
5657
5658         // if already loaded just return it, otherwise make a new skinframe
5659         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5660         if (skinframe && skinframe->base)
5661                 return skinframe;
5662
5663         skinframe->stain = NULL;
5664         skinframe->merged = NULL;
5665         skinframe->base = NULL;
5666         skinframe->pants = NULL;
5667         skinframe->shirt = NULL;
5668         skinframe->nmap = NULL;
5669         skinframe->gloss = NULL;
5670         skinframe->glow = NULL;
5671         skinframe->fog = NULL;
5672         skinframe->reflect = NULL;
5673         skinframe->hasalpha = false;
5674
5675         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5676         if (!skindata)
5677                 return NULL;
5678
5679         if (developer_loading.integer)
5680                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5681
5682         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5683         {
5684                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5685                 temp2 = temp1 + width * height * 4;
5686                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5687                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5688                 Mem_Free(temp1);
5689         }
5690         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5691         if (textureflags & TEXF_ALPHA)
5692         {
5693                 for (i = 3;i < width * height * 4;i += 4)
5694                 {
5695                         if (skindata[i] < 255)
5696                         {
5697                                 skinframe->hasalpha = true;
5698                                 break;
5699                         }
5700                 }
5701                 if (r_loadfog && skinframe->hasalpha)
5702                 {
5703                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5704                         memcpy(fogpixels, skindata, width * height * 4);
5705                         for (i = 0;i < width * height * 4;i += 4)
5706                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5707                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5708                         Mem_Free(fogpixels);
5709                 }
5710         }
5711
5712         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5713         //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]);
5714
5715         return skinframe;
5716 }
5717
5718 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5719 {
5720         int i;
5721         int featuresmask;
5722         skinframe_t *skinframe;
5723
5724         if (cls.state == ca_dedicated)
5725                 return NULL;
5726
5727         // if already loaded just return it, otherwise make a new skinframe
5728         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5729         if (skinframe && skinframe->base)
5730                 return skinframe;
5731
5732         skinframe->stain = NULL;
5733         skinframe->merged = NULL;
5734         skinframe->base = NULL;
5735         skinframe->pants = NULL;
5736         skinframe->shirt = NULL;
5737         skinframe->nmap = NULL;
5738         skinframe->gloss = NULL;
5739         skinframe->glow = NULL;
5740         skinframe->fog = NULL;
5741         skinframe->reflect = NULL;
5742         skinframe->hasalpha = false;
5743
5744         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5745         if (!skindata)
5746                 return NULL;
5747
5748         if (developer_loading.integer)
5749                 Con_Printf("loading quake skin \"%s\"\n", name);
5750
5751         // 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)
5752         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5753         memcpy(skinframe->qpixels, skindata, width*height);
5754         skinframe->qwidth = width;
5755         skinframe->qheight = height;
5756
5757         featuresmask = 0;
5758         for (i = 0;i < width * height;i++)
5759                 featuresmask |= palette_featureflags[skindata[i]];
5760
5761         skinframe->hasalpha = false;
5762         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5763         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5764         skinframe->qgeneratemerged = true;
5765         skinframe->qgeneratebase = skinframe->qhascolormapping;
5766         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5767
5768         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5769         //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]);
5770
5771         return skinframe;
5772 }
5773
5774 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5775 {
5776         int width;
5777         int height;
5778         unsigned char *skindata;
5779
5780         if (!skinframe->qpixels)
5781                 return;
5782
5783         if (!skinframe->qhascolormapping)
5784                 colormapped = false;
5785
5786         if (colormapped)
5787         {
5788                 if (!skinframe->qgeneratebase)
5789                         return;
5790         }
5791         else
5792         {
5793                 if (!skinframe->qgeneratemerged)
5794                         return;
5795         }
5796
5797         width = skinframe->qwidth;
5798         height = skinframe->qheight;
5799         skindata = skinframe->qpixels;
5800
5801         if (skinframe->qgeneratenmap)
5802         {
5803                 unsigned char *temp1, *temp2;
5804                 skinframe->qgeneratenmap = false;
5805                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5806                 temp2 = temp1 + width * height * 4;
5807                 // use either a custom palette or the quake palette
5808                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5809                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5810                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5811                 Mem_Free(temp1);
5812         }
5813
5814         if (skinframe->qgenerateglow)
5815         {
5816                 skinframe->qgenerateglow = false;
5817                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5818         }
5819
5820         if (colormapped)
5821         {
5822                 skinframe->qgeneratebase = false;
5823                 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);
5824                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5825                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5826         }
5827         else
5828         {
5829                 skinframe->qgeneratemerged = false;
5830                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5831         }
5832
5833         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5834         {
5835                 Mem_Free(skinframe->qpixels);
5836                 skinframe->qpixels = NULL;
5837         }
5838 }
5839
5840 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)
5841 {
5842         int i;
5843         skinframe_t *skinframe;
5844
5845         if (cls.state == ca_dedicated)
5846                 return NULL;
5847
5848         // if already loaded just return it, otherwise make a new skinframe
5849         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5850         if (skinframe && skinframe->base)
5851                 return skinframe;
5852
5853         skinframe->stain = NULL;
5854         skinframe->merged = NULL;
5855         skinframe->base = NULL;
5856         skinframe->pants = NULL;
5857         skinframe->shirt = NULL;
5858         skinframe->nmap = NULL;
5859         skinframe->gloss = NULL;
5860         skinframe->glow = NULL;
5861         skinframe->fog = NULL;
5862         skinframe->reflect = NULL;
5863         skinframe->hasalpha = false;
5864
5865         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5866         if (!skindata)
5867                 return NULL;
5868
5869         if (developer_loading.integer)
5870                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5871
5872         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5873         if (textureflags & TEXF_ALPHA)
5874         {
5875                 for (i = 0;i < width * height;i++)
5876                 {
5877                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5878                         {
5879                                 skinframe->hasalpha = true;
5880                                 break;
5881                         }
5882                 }
5883                 if (r_loadfog && skinframe->hasalpha)
5884                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5885         }
5886
5887         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5888         //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]);
5889
5890         return skinframe;
5891 }
5892
5893 skinframe_t *R_SkinFrame_LoadMissing(void)
5894 {
5895         skinframe_t *skinframe;
5896
5897         if (cls.state == ca_dedicated)
5898                 return NULL;
5899
5900         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5901         skinframe->stain = NULL;
5902         skinframe->merged = NULL;
5903         skinframe->base = NULL;
5904         skinframe->pants = NULL;
5905         skinframe->shirt = NULL;
5906         skinframe->nmap = NULL;
5907         skinframe->gloss = NULL;
5908         skinframe->glow = NULL;
5909         skinframe->fog = NULL;
5910         skinframe->reflect = NULL;
5911         skinframe->hasalpha = false;
5912
5913         skinframe->avgcolor[0] = rand() / RAND_MAX;
5914         skinframe->avgcolor[1] = rand() / RAND_MAX;
5915         skinframe->avgcolor[2] = rand() / RAND_MAX;
5916         skinframe->avgcolor[3] = 1;
5917
5918         return skinframe;
5919 }
5920
5921 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5922 typedef struct suffixinfo_s
5923 {
5924         char *suffix;
5925         qboolean flipx, flipy, flipdiagonal;
5926 }
5927 suffixinfo_t;
5928 static suffixinfo_t suffix[3][6] =
5929 {
5930         {
5931                 {"px",   false, false, false},
5932                 {"nx",   false, false, false},
5933                 {"py",   false, false, false},
5934                 {"ny",   false, false, false},
5935                 {"pz",   false, false, false},
5936                 {"nz",   false, false, false}
5937         },
5938         {
5939                 {"posx", false, false, false},
5940                 {"negx", false, false, false},
5941                 {"posy", false, false, false},
5942                 {"negy", false, false, false},
5943                 {"posz", false, false, false},
5944                 {"negz", false, false, false}
5945         },
5946         {
5947                 {"rt",    true, false,  true},
5948                 {"lf",   false,  true,  true},
5949                 {"ft",    true,  true, false},
5950                 {"bk",   false, false, false},
5951                 {"up",    true, false,  true},
5952                 {"dn",    true, false,  true}
5953         }
5954 };
5955
5956 static int componentorder[4] = {0, 1, 2, 3};
5957
5958 rtexture_t *R_LoadCubemap(const char *basename)
5959 {
5960         int i, j, cubemapsize;
5961         unsigned char *cubemappixels, *image_buffer;
5962         rtexture_t *cubemaptexture;
5963         char name[256];
5964         // must start 0 so the first loadimagepixels has no requested width/height
5965         cubemapsize = 0;
5966         cubemappixels = NULL;
5967         cubemaptexture = NULL;
5968         // keep trying different suffix groups (posx, px, rt) until one loads
5969         for (j = 0;j < 3 && !cubemappixels;j++)
5970         {
5971                 // load the 6 images in the suffix group
5972                 for (i = 0;i < 6;i++)
5973                 {
5974                         // generate an image name based on the base and and suffix
5975                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5976                         // load it
5977                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5978                         {
5979                                 // an image loaded, make sure width and height are equal
5980                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5981                                 {
5982                                         // if this is the first image to load successfully, allocate the cubemap memory
5983                                         if (!cubemappixels && image_width >= 1)
5984                                         {
5985                                                 cubemapsize = image_width;
5986                                                 // note this clears to black, so unavailable sides are black
5987                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5988                                         }
5989                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5990                                         if (cubemappixels)
5991                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
5992                                 }
5993                                 else
5994                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5995                                 // free the image
5996                                 Mem_Free(image_buffer);
5997                         }
5998                 }
5999         }
6000         // if a cubemap loaded, upload it
6001         if (cubemappixels)
6002         {
6003                 if (developer_loading.integer)
6004                         Con_Printf("loading cubemap \"%s\"\n", basename);
6005
6006                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6007                 Mem_Free(cubemappixels);
6008         }
6009         else
6010         {
6011                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6012                 if (developer_loading.integer)
6013                 {
6014                         Con_Printf("(tried tried images ");
6015                         for (j = 0;j < 3;j++)
6016                                 for (i = 0;i < 6;i++)
6017                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6018                         Con_Print(" and was unable to find any of them).\n");
6019                 }
6020         }
6021         return cubemaptexture;
6022 }
6023
6024 rtexture_t *R_GetCubemap(const char *basename)
6025 {
6026         int i;
6027         for (i = 0;i < r_texture_numcubemaps;i++)
6028                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6029                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6030         if (i >= MAX_CUBEMAPS)
6031                 return r_texture_whitecube;
6032         r_texture_numcubemaps++;
6033         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6034         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6035         return r_texture_cubemaps[i].texture;
6036 }
6037
6038 void R_FreeCubemaps(void)
6039 {
6040         int i;
6041         for (i = 0;i < r_texture_numcubemaps;i++)
6042         {
6043                 if (developer_loading.integer)
6044                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6045                 if (r_texture_cubemaps[i].texture)
6046                         R_FreeTexture(r_texture_cubemaps[i].texture);
6047         }
6048         r_texture_numcubemaps = 0;
6049 }
6050
6051 void R_Main_FreeViewCache(void)
6052 {
6053         if (r_refdef.viewcache.entityvisible)
6054                 Mem_Free(r_refdef.viewcache.entityvisible);
6055         if (r_refdef.viewcache.world_pvsbits)
6056                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6057         if (r_refdef.viewcache.world_leafvisible)
6058                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6059         if (r_refdef.viewcache.world_surfacevisible)
6060                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6061         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6062 }
6063
6064 void R_Main_ResizeViewCache(void)
6065 {
6066         int numentities = r_refdef.scene.numentities;
6067         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6068         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6069         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6070         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6071         if (r_refdef.viewcache.maxentities < numentities)
6072         {
6073                 r_refdef.viewcache.maxentities = numentities;
6074                 if (r_refdef.viewcache.entityvisible)
6075                         Mem_Free(r_refdef.viewcache.entityvisible);
6076                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6077         }
6078         if (r_refdef.viewcache.world_numclusters != numclusters)
6079         {
6080                 r_refdef.viewcache.world_numclusters = numclusters;
6081                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6082                 if (r_refdef.viewcache.world_pvsbits)
6083                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6084                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6085         }
6086         if (r_refdef.viewcache.world_numleafs != numleafs)
6087         {
6088                 r_refdef.viewcache.world_numleafs = numleafs;
6089                 if (r_refdef.viewcache.world_leafvisible)
6090                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6091                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6092         }
6093         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6094         {
6095                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6096                 if (r_refdef.viewcache.world_surfacevisible)
6097                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6098                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6099         }
6100 }
6101
6102 extern rtexture_t *loadingscreentexture;
6103 void gl_main_start(void)
6104 {
6105         loadingscreentexture = NULL;
6106         r_texture_blanknormalmap = NULL;
6107         r_texture_white = NULL;
6108         r_texture_grey128 = NULL;
6109         r_texture_black = NULL;
6110         r_texture_whitecube = NULL;
6111         r_texture_normalizationcube = NULL;
6112         r_texture_fogattenuation = NULL;
6113         r_texture_gammaramps = NULL;
6114         r_texture_numcubemaps = 0;
6115
6116         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6117         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6118
6119         switch(vid.renderpath)
6120         {
6121         case RENDERPATH_GL20:
6122         case RENDERPATH_CGGL:
6123                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6124                 Cvar_SetValueQuick(&gl_combine, 1);
6125                 Cvar_SetValueQuick(&r_glsl, 1);
6126                 r_loadnormalmap = true;
6127                 r_loadgloss = true;
6128                 r_loadfog = false;
6129                 break;
6130         case RENDERPATH_GL13:
6131                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6132                 Cvar_SetValueQuick(&gl_combine, 1);
6133                 Cvar_SetValueQuick(&r_glsl, 0);
6134                 r_loadnormalmap = false;
6135                 r_loadgloss = false;
6136                 r_loadfog = true;
6137                 break;
6138         case RENDERPATH_GL11:
6139                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6140                 Cvar_SetValueQuick(&gl_combine, 0);
6141                 Cvar_SetValueQuick(&r_glsl, 0);
6142                 r_loadnormalmap = false;
6143                 r_loadgloss = false;
6144                 r_loadfog = true;
6145                 break;
6146         }
6147
6148         R_AnimCache_Free();
6149         R_FrameData_Reset();
6150
6151         r_numqueries = 0;
6152         r_maxqueries = 0;
6153         memset(r_queries, 0, sizeof(r_queries));
6154
6155         r_qwskincache = NULL;
6156         r_qwskincache_size = 0;
6157
6158         // set up r_skinframe loading system for textures
6159         memset(&r_skinframe, 0, sizeof(r_skinframe));
6160         r_skinframe.loadsequence = 1;
6161         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6162
6163         r_main_texturepool = R_AllocTexturePool();
6164         R_BuildBlankTextures();
6165         R_BuildNoTexture();
6166         if (vid.support.arb_texture_cube_map)
6167         {
6168                 R_BuildWhiteCube();
6169                 R_BuildNormalizationCube();
6170         }
6171         r_texture_fogattenuation = NULL;
6172         r_texture_gammaramps = NULL;
6173         //r_texture_fogintensity = NULL;
6174         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6175         memset(&r_waterstate, 0, sizeof(r_waterstate));
6176         r_glsl_permutation = NULL;
6177         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6178         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6179         glslshaderstring = NULL;
6180 #ifdef SUPPORTCG
6181         r_cg_permutation = NULL;
6182         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6183         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6184         cgshaderstring = NULL;
6185 #endif
6186         memset(&r_svbsp, 0, sizeof (r_svbsp));
6187
6188         r_refdef.fogmasktable_density = 0;
6189 }
6190
6191 void gl_main_shutdown(void)
6192 {
6193         R_AnimCache_Free();
6194         R_FrameData_Reset();
6195
6196         R_Main_FreeViewCache();
6197
6198         if (r_maxqueries)
6199                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6200
6201         r_numqueries = 0;
6202         r_maxqueries = 0;
6203         memset(r_queries, 0, sizeof(r_queries));
6204
6205         r_qwskincache = NULL;
6206         r_qwskincache_size = 0;
6207
6208         // clear out the r_skinframe state
6209         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6210         memset(&r_skinframe, 0, sizeof(r_skinframe));
6211
6212         if (r_svbsp.nodes)
6213                 Mem_Free(r_svbsp.nodes);
6214         memset(&r_svbsp, 0, sizeof (r_svbsp));
6215         R_FreeTexturePool(&r_main_texturepool);
6216         loadingscreentexture = NULL;
6217         r_texture_blanknormalmap = NULL;
6218         r_texture_white = NULL;
6219         r_texture_grey128 = NULL;
6220         r_texture_black = NULL;
6221         r_texture_whitecube = NULL;
6222         r_texture_normalizationcube = NULL;
6223         r_texture_fogattenuation = NULL;
6224         r_texture_gammaramps = NULL;
6225         r_texture_numcubemaps = 0;
6226         //r_texture_fogintensity = NULL;
6227         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6228         memset(&r_waterstate, 0, sizeof(r_waterstate));
6229         r_glsl_permutation = NULL;
6230         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6231         glslshaderstring = NULL;
6232 #ifdef SUPPORTCG
6233         r_cg_permutation = NULL;
6234         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6235         cgshaderstring = NULL;
6236 #endif
6237         R_GLSL_Restart_f();
6238 }
6239
6240 extern void CL_ParseEntityLump(char *entitystring);
6241 void gl_main_newmap(void)
6242 {
6243         // FIXME: move this code to client
6244         int l;
6245         char *entities, entname[MAX_QPATH];
6246         if (r_qwskincache)
6247                 Mem_Free(r_qwskincache);
6248         r_qwskincache = NULL;
6249         r_qwskincache_size = 0;
6250         if (cl.worldmodel)
6251         {
6252                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6253                 l = (int)strlen(entname) - 4;
6254                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6255                 {
6256                         memcpy(entname + l, ".ent", 5);
6257                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6258                         {
6259                                 CL_ParseEntityLump(entities);
6260                                 Mem_Free(entities);
6261                                 return;
6262                         }
6263                 }
6264                 if (cl.worldmodel->brush.entities)
6265                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6266         }
6267         R_Main_FreeViewCache();
6268
6269         R_FrameData_Reset();
6270 }
6271
6272 void GL_Main_Init(void)
6273 {
6274         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6275
6276         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6277         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6278         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6279         if (gamemode == GAME_NEHAHRA)
6280         {
6281                 Cvar_RegisterVariable (&gl_fogenable);
6282                 Cvar_RegisterVariable (&gl_fogdensity);
6283                 Cvar_RegisterVariable (&gl_fogred);
6284                 Cvar_RegisterVariable (&gl_foggreen);
6285                 Cvar_RegisterVariable (&gl_fogblue);
6286                 Cvar_RegisterVariable (&gl_fogstart);
6287                 Cvar_RegisterVariable (&gl_fogend);
6288                 Cvar_RegisterVariable (&gl_skyclip);
6289         }
6290         Cvar_RegisterVariable(&r_motionblur);
6291         Cvar_RegisterVariable(&r_motionblur_maxblur);
6292         Cvar_RegisterVariable(&r_motionblur_bmin);
6293         Cvar_RegisterVariable(&r_motionblur_vmin);
6294         Cvar_RegisterVariable(&r_motionblur_vmax);
6295         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6296         Cvar_RegisterVariable(&r_motionblur_randomize);
6297         Cvar_RegisterVariable(&r_damageblur);
6298         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6299         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6300         Cvar_RegisterVariable(&r_equalize_entities_by);
6301         Cvar_RegisterVariable(&r_equalize_entities_to);
6302         Cvar_RegisterVariable(&r_depthfirst);
6303         Cvar_RegisterVariable(&r_useinfinitefarclip);
6304         Cvar_RegisterVariable(&r_farclip_base);
6305         Cvar_RegisterVariable(&r_farclip_world);
6306         Cvar_RegisterVariable(&r_nearclip);
6307         Cvar_RegisterVariable(&r_showbboxes);
6308         Cvar_RegisterVariable(&r_showsurfaces);
6309         Cvar_RegisterVariable(&r_showtris);
6310         Cvar_RegisterVariable(&r_shownormals);
6311         Cvar_RegisterVariable(&r_showlighting);
6312         Cvar_RegisterVariable(&r_showshadowvolumes);
6313         Cvar_RegisterVariable(&r_showcollisionbrushes);
6314         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6315         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6316         Cvar_RegisterVariable(&r_showdisabledepthtest);
6317         Cvar_RegisterVariable(&r_drawportals);
6318         Cvar_RegisterVariable(&r_drawentities);
6319         Cvar_RegisterVariable(&r_cullentities_trace);
6320         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6321         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6322         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6323         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6324         Cvar_RegisterVariable(&r_drawviewmodel);
6325         Cvar_RegisterVariable(&r_speeds);
6326         Cvar_RegisterVariable(&r_fullbrights);
6327         Cvar_RegisterVariable(&r_wateralpha);
6328         Cvar_RegisterVariable(&r_dynamic);
6329         Cvar_RegisterVariable(&r_fullbright);
6330         Cvar_RegisterVariable(&r_shadows);
6331         Cvar_RegisterVariable(&r_shadows_darken);
6332         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6333         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6334         Cvar_RegisterVariable(&r_shadows_throwdistance);
6335         Cvar_RegisterVariable(&r_shadows_throwdirection);
6336         Cvar_RegisterVariable(&r_shadows_focus);
6337         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6338         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6339         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6340         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6341         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6342         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6343         Cvar_RegisterVariable(&r_fog_exp2);
6344         Cvar_RegisterVariable(&r_drawfog);
6345         Cvar_RegisterVariable(&r_transparentdepthmasking);
6346         Cvar_RegisterVariable(&r_texture_dds_load);
6347         Cvar_RegisterVariable(&r_texture_dds_save);
6348         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6349         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6350         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6351         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6352         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6353         Cvar_RegisterVariable(&r_textureunits);
6354         Cvar_RegisterVariable(&gl_combine);
6355         Cvar_RegisterVariable(&r_glsl);
6356         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6357         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6358         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6359         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6360         Cvar_RegisterVariable(&r_glsl_postprocess);
6361         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6362         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6363         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6364         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6365         Cvar_RegisterVariable(&r_water);
6366         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6367         Cvar_RegisterVariable(&r_water_clippingplanebias);
6368         Cvar_RegisterVariable(&r_water_refractdistort);
6369         Cvar_RegisterVariable(&r_water_reflectdistort);
6370         Cvar_RegisterVariable(&r_lerpsprites);
6371         Cvar_RegisterVariable(&r_lerpmodels);
6372         Cvar_RegisterVariable(&r_lerplightstyles);
6373         Cvar_RegisterVariable(&r_waterscroll);
6374         Cvar_RegisterVariable(&r_bloom);
6375         Cvar_RegisterVariable(&r_bloom_colorscale);
6376         Cvar_RegisterVariable(&r_bloom_brighten);
6377         Cvar_RegisterVariable(&r_bloom_blur);
6378         Cvar_RegisterVariable(&r_bloom_resolution);
6379         Cvar_RegisterVariable(&r_bloom_colorexponent);
6380         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6381         Cvar_RegisterVariable(&r_hdr);
6382         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6383         Cvar_RegisterVariable(&r_hdr_glowintensity);
6384         Cvar_RegisterVariable(&r_hdr_range);
6385         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6386         Cvar_RegisterVariable(&developer_texturelogging);
6387         Cvar_RegisterVariable(&gl_lightmaps);
6388         Cvar_RegisterVariable(&r_test);
6389         Cvar_RegisterVariable(&r_batchmode);
6390         Cvar_RegisterVariable(&r_glsl_saturation);
6391         Cvar_RegisterVariable(&r_framedatasize);
6392         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6393                 Cvar_SetValue("r_fullbrights", 0);
6394         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6395
6396         Cvar_RegisterVariable(&r_track_sprites);
6397         Cvar_RegisterVariable(&r_track_sprites_flags);
6398         Cvar_RegisterVariable(&r_track_sprites_scalew);
6399         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6400         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6401         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6402 }
6403
6404 extern void R_Textures_Init(void);
6405 extern void GL_Draw_Init(void);
6406 extern void GL_Main_Init(void);
6407 extern void R_Shadow_Init(void);
6408 extern void R_Sky_Init(void);
6409 extern void GL_Surf_Init(void);
6410 extern void R_Particles_Init(void);
6411 extern void R_Explosion_Init(void);
6412 extern void gl_backend_init(void);
6413 extern void Sbar_Init(void);
6414 extern void R_LightningBeams_Init(void);
6415 extern void Mod_RenderInit(void);
6416 extern void Font_Init(void);
6417
6418 void Render_Init(void)
6419 {
6420         gl_backend_init();
6421         R_Textures_Init();
6422         GL_Main_Init();
6423         Font_Init();
6424         GL_Draw_Init();
6425         R_Shadow_Init();
6426         R_Sky_Init();
6427         GL_Surf_Init();
6428         Sbar_Init();
6429         R_Particles_Init();
6430         R_Explosion_Init();
6431         R_LightningBeams_Init();
6432         Mod_RenderInit();
6433 }
6434
6435 /*
6436 ===============
6437 GL_Init
6438 ===============
6439 */
6440 extern char *ENGINE_EXTENSIONS;
6441 void GL_Init (void)
6442 {
6443         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6444         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6445         gl_version = (const char *)qglGetString(GL_VERSION);
6446         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6447
6448         if (!gl_extensions)
6449                 gl_extensions = "";
6450         if (!gl_platformextensions)
6451                 gl_platformextensions = "";
6452
6453         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6454         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6455         Con_Printf("GL_VERSION: %s\n", gl_version);
6456         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6457         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6458
6459         VID_CheckExtensions();
6460
6461         // LordHavoc: report supported extensions
6462         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6463
6464         // clear to black (loading plaque will be seen over this)
6465         CHECKGLERROR
6466         qglClearColor(0,0,0,1);CHECKGLERROR
6467         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6468 }
6469
6470 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6471 {
6472         int i;
6473         mplane_t *p;
6474         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6475         {
6476                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6477                 if (i == 4)
6478                         continue;
6479                 p = r_refdef.view.frustum + i;
6480                 switch(p->signbits)
6481                 {
6482                 default:
6483                 case 0:
6484                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6485                                 return true;
6486                         break;
6487                 case 1:
6488                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6489                                 return true;
6490                         break;
6491                 case 2:
6492                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6493                                 return true;
6494                         break;
6495                 case 3:
6496                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6497                                 return true;
6498                         break;
6499                 case 4:
6500                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6501                                 return true;
6502                         break;
6503                 case 5:
6504                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6505                                 return true;
6506                         break;
6507                 case 6:
6508                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6509                                 return true;
6510                         break;
6511                 case 7:
6512                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6513                                 return true;
6514                         break;
6515                 }
6516         }
6517         return false;
6518 }
6519
6520 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6521 {
6522         int i;
6523         const mplane_t *p;
6524         for (i = 0;i < numplanes;i++)
6525         {
6526                 p = planes + i;
6527                 switch(p->signbits)
6528                 {
6529                 default:
6530                 case 0:
6531                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6532                                 return true;
6533                         break;
6534                 case 1:
6535                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6536                                 return true;
6537                         break;
6538                 case 2:
6539                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6540                                 return true;
6541                         break;
6542                 case 3:
6543                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6544                                 return true;
6545                         break;
6546                 case 4:
6547                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6548                                 return true;
6549                         break;
6550                 case 5:
6551                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6552                                 return true;
6553                         break;
6554                 case 6:
6555                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6556                                 return true;
6557                         break;
6558                 case 7:
6559                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6560                                 return true;
6561                         break;
6562                 }
6563         }
6564         return false;
6565 }
6566
6567 //==================================================================================
6568
6569 // LordHavoc: this stores temporary data used within the same frame
6570
6571 qboolean r_framedata_failed;
6572 static size_t r_framedata_size;
6573 static size_t r_framedata_current;
6574 static void *r_framedata_base;
6575
6576 void R_FrameData_Reset(void)
6577 {
6578         if (r_framedata_base)
6579                 Mem_Free(r_framedata_base);
6580         r_framedata_base = NULL;
6581         r_framedata_size = 0;
6582         r_framedata_current = 0;
6583         r_framedata_failed = false;
6584 }
6585
6586 void R_FrameData_NewFrame(void)
6587 {
6588         size_t wantedsize;
6589         if (r_framedata_failed)
6590                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6591         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6592         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6593         if (r_framedata_size != wantedsize)
6594         {
6595                 r_framedata_size = wantedsize;
6596                 if (r_framedata_base)
6597                         Mem_Free(r_framedata_base);
6598                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6599         }
6600         r_framedata_current = 0;
6601         r_framedata_failed = false;
6602 }
6603
6604 void *R_FrameData_Alloc(size_t size)
6605 {
6606         void *data;
6607
6608         // align to 16 byte boundary
6609         size = (size + 15) & ~15;
6610         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6611         r_framedata_current += size;
6612
6613         // check overflow
6614         if (r_framedata_current > r_framedata_size)
6615                 r_framedata_failed = true;
6616
6617         // return NULL on everything after a failure
6618         if (r_framedata_failed)
6619                 return NULL;
6620
6621         return data;
6622 }
6623
6624 void *R_FrameData_Store(size_t size, void *data)
6625 {
6626         void *d = R_FrameData_Alloc(size);
6627         if (d)
6628                 memcpy(d, data, size);
6629         return d;
6630 }
6631
6632 //==================================================================================
6633
6634 // LordHavoc: animcache originally written by Echon, rewritten since then
6635
6636 /**
6637  * Animation cache prevents re-generating mesh data for an animated model
6638  * multiple times in one frame for lighting, shadowing, reflections, etc.
6639  */
6640
6641 void R_AnimCache_Free(void)
6642 {
6643 }
6644
6645 void R_AnimCache_ClearCache(void)
6646 {
6647         int i;
6648         entity_render_t *ent;
6649
6650         for (i = 0;i < r_refdef.scene.numentities;i++)
6651         {
6652                 ent = r_refdef.scene.entities[i];
6653                 ent->animcache_vertex3f = NULL;
6654                 ent->animcache_normal3f = NULL;
6655                 ent->animcache_svector3f = NULL;
6656                 ent->animcache_tvector3f = NULL;
6657         }
6658 }
6659
6660 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6661 {
6662         dp_model_t *model = ent->model;
6663         int numvertices;
6664         // see if it's already cached this frame
6665         if (ent->animcache_vertex3f)
6666         {
6667                 // add normals/tangents if needed
6668                 if (wantnormals || wanttangents)
6669                 {
6670                         if (ent->animcache_normal3f)
6671                                 wantnormals = false;
6672                         if (ent->animcache_svector3f)
6673                                 wanttangents = false;
6674                         if (wantnormals || wanttangents)
6675                         {
6676                                 numvertices = model->surfmesh.num_vertices;
6677                                 if (wantnormals)
6678                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6679                                 if (wanttangents)
6680                                 {
6681                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6682                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6683                                 }
6684                                 if (!r_framedata_failed)
6685                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6686                         }
6687                 }
6688         }
6689         else
6690         {
6691                 // see if this ent is worth caching
6692                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6693                         return false;
6694                 // get some memory for this entity and generate mesh data
6695                 numvertices = model->surfmesh.num_vertices;
6696                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6697                 if (wantnormals)
6698                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6699                 if (wanttangents)
6700                 {
6701                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6702                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6703                 }
6704                 if (!r_framedata_failed)
6705                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6706         }
6707         return !r_framedata_failed;
6708 }
6709
6710 void R_AnimCache_CacheVisibleEntities(void)
6711 {
6712         int i;
6713         qboolean wantnormals = !r_showsurfaces.integer;
6714         qboolean wanttangents = !r_showsurfaces.integer;
6715
6716         switch(vid.renderpath)
6717         {
6718         case RENDERPATH_GL20:
6719         case RENDERPATH_CGGL:
6720                 break;
6721         case RENDERPATH_GL13:
6722         case RENDERPATH_GL11:
6723                 wanttangents = false;
6724                 break;
6725         }
6726
6727         // TODO: thread this
6728         // NOTE: R_PrepareRTLights() also caches entities
6729
6730         for (i = 0;i < r_refdef.scene.numentities;i++)
6731                 if (r_refdef.viewcache.entityvisible[i])
6732                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6733 }
6734
6735 //==================================================================================
6736
6737 static void R_View_UpdateEntityLighting (void)
6738 {
6739         int i;
6740         entity_render_t *ent;
6741         vec3_t tempdiffusenormal, avg;
6742         vec_t f, fa, fd, fdd;
6743         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6744
6745         for (i = 0;i < r_refdef.scene.numentities;i++)
6746         {
6747                 ent = r_refdef.scene.entities[i];
6748
6749                 // skip unseen models
6750                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6751                         continue;
6752
6753                 // skip bsp models
6754                 if (ent->model && ent->model->brush.num_leafs)
6755                 {
6756                         // TODO: use modellight for r_ambient settings on world?
6757                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6758                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6759                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6760                         continue;
6761                 }
6762
6763                 // fetch the lighting from the worldmodel data
6764                 VectorClear(ent->modellight_ambient);
6765                 VectorClear(ent->modellight_diffuse);
6766                 VectorClear(tempdiffusenormal);
6767                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6768                 {
6769                         vec3_t org;
6770                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6771                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6772                         if(ent->flags & RENDER_EQUALIZE)
6773                         {
6774                                 // first fix up ambient lighting...
6775                                 if(r_equalize_entities_minambient.value > 0)
6776                                 {
6777                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6778                                         if(fd > 0)
6779                                         {
6780                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6781                                                 if(fa < r_equalize_entities_minambient.value * fd)
6782                                                 {
6783                                                         // solve:
6784                                                         //   fa'/fd' = minambient
6785                                                         //   fa'+0.25*fd' = fa+0.25*fd
6786                                                         //   ...
6787                                                         //   fa' = fd' * minambient
6788                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6789                                                         //   ...
6790                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6791                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6792                                                         //   ...
6793                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6794                                                         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
6795                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6796                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6797                                                 }
6798                                         }
6799                                 }
6800
6801                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6802                                 {
6803                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6804                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6805                                         if(f > 0)
6806                                         {
6807                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6808                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6809                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6810                                         }
6811                                 }
6812                         }
6813                 }
6814                 else // highly rare
6815                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6816
6817                 // move the light direction into modelspace coordinates for lighting code
6818                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6819                 if(VectorLength2(ent->modellight_lightdir) == 0)
6820                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6821                 VectorNormalize(ent->modellight_lightdir);
6822         }
6823 }
6824
6825 #define MAX_LINEOFSIGHTTRACES 64
6826
6827 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6828 {
6829         int i;
6830         vec3_t boxmins, boxmaxs;
6831         vec3_t start;
6832         vec3_t end;
6833         dp_model_t *model = r_refdef.scene.worldmodel;
6834
6835         if (!model || !model->brush.TraceLineOfSight)
6836                 return true;
6837
6838         // expand the box a little
6839         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6840         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6841         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6842         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6843         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6844         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6845
6846         // return true if eye is inside enlarged box
6847         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6848                 return true;
6849
6850         // try center
6851         VectorCopy(eye, start);
6852         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6853         if (model->brush.TraceLineOfSight(model, start, end))
6854                 return true;
6855
6856         // try various random positions
6857         for (i = 0;i < numsamples;i++)
6858         {
6859                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6860                 if (model->brush.TraceLineOfSight(model, start, end))
6861                         return true;
6862         }
6863
6864         return false;
6865 }
6866
6867
6868 static void R_View_UpdateEntityVisible (void)
6869 {
6870         int i;
6871         int renderimask;
6872         int samples;
6873         entity_render_t *ent;
6874
6875         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6876                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6877                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6878                 :                                                          RENDER_EXTERIORMODEL;
6879         if (!r_drawviewmodel.integer)
6880                 renderimask |= RENDER_VIEWMODEL;
6881         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6882         {
6883                 // worldmodel can check visibility
6884                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6885                 for (i = 0;i < r_refdef.scene.numentities;i++)
6886                 {
6887                         ent = r_refdef.scene.entities[i];
6888                         if (!(ent->flags & renderimask))
6889                         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)))
6890                         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))
6891                                 r_refdef.viewcache.entityvisible[i] = true;
6892                 }
6893                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6894                 {
6895                         for (i = 0;i < r_refdef.scene.numentities;i++)
6896                         {
6897                                 ent = r_refdef.scene.entities[i];
6898                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6899                                 {
6900                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6901                                         if (samples < 0)
6902                                                 continue; // temp entities do pvs only
6903                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6904                                                 ent->last_trace_visibility = realtime;
6905                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6906                                                 r_refdef.viewcache.entityvisible[i] = 0;
6907                                 }
6908                         }
6909                 }
6910         }
6911         else
6912         {
6913                 // no worldmodel or it can't check visibility
6914                 for (i = 0;i < r_refdef.scene.numentities;i++)
6915                 {
6916                         ent = r_refdef.scene.entities[i];
6917                         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));
6918                 }
6919         }
6920 }
6921
6922 /// only used if skyrendermasked, and normally returns false
6923 int R_DrawBrushModelsSky (void)
6924 {
6925         int i, sky;
6926         entity_render_t *ent;
6927
6928         sky = false;
6929         for (i = 0;i < r_refdef.scene.numentities;i++)
6930         {
6931                 if (!r_refdef.viewcache.entityvisible[i])
6932                         continue;
6933                 ent = r_refdef.scene.entities[i];
6934                 if (!ent->model || !ent->model->DrawSky)
6935                         continue;
6936                 ent->model->DrawSky(ent);
6937                 sky = true;
6938         }
6939         return sky;
6940 }
6941
6942 static void R_DrawNoModel(entity_render_t *ent);
6943 static void R_DrawModels(void)
6944 {
6945         int i;
6946         entity_render_t *ent;
6947
6948         for (i = 0;i < r_refdef.scene.numentities;i++)
6949         {
6950                 if (!r_refdef.viewcache.entityvisible[i])
6951                         continue;
6952                 ent = r_refdef.scene.entities[i];
6953                 r_refdef.stats.entities++;
6954                 if (ent->model && ent->model->Draw != NULL)
6955                         ent->model->Draw(ent);
6956                 else
6957                         R_DrawNoModel(ent);
6958         }
6959 }
6960
6961 static void R_DrawModelsDepth(void)
6962 {
6963         int i;
6964         entity_render_t *ent;
6965
6966         for (i = 0;i < r_refdef.scene.numentities;i++)
6967         {
6968                 if (!r_refdef.viewcache.entityvisible[i])
6969                         continue;
6970                 ent = r_refdef.scene.entities[i];
6971                 if (ent->model && ent->model->DrawDepth != NULL)
6972                         ent->model->DrawDepth(ent);
6973         }
6974 }
6975
6976 static void R_DrawModelsDebug(void)
6977 {
6978         int i;
6979         entity_render_t *ent;
6980
6981         for (i = 0;i < r_refdef.scene.numentities;i++)
6982         {
6983                 if (!r_refdef.viewcache.entityvisible[i])
6984                         continue;
6985                 ent = r_refdef.scene.entities[i];
6986                 if (ent->model && ent->model->DrawDebug != NULL)
6987                         ent->model->DrawDebug(ent);
6988         }
6989 }
6990
6991 static void R_DrawModelsAddWaterPlanes(void)
6992 {
6993         int i;
6994         entity_render_t *ent;
6995
6996         for (i = 0;i < r_refdef.scene.numentities;i++)
6997         {
6998                 if (!r_refdef.viewcache.entityvisible[i])
6999                         continue;
7000                 ent = r_refdef.scene.entities[i];
7001                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7002                         ent->model->DrawAddWaterPlanes(ent);
7003         }
7004 }
7005
7006 static void R_View_SetFrustum(void)
7007 {
7008         int i;
7009         double slopex, slopey;
7010         vec3_t forward, left, up, origin;
7011
7012         // we can't trust r_refdef.view.forward and friends in reflected scenes
7013         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7014
7015 #if 0
7016         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7017         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7018         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7019         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7020         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7021         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7022         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7023         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7024         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7025         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7026         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7027         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7028 #endif
7029
7030 #if 0
7031         zNear = r_refdef.nearclip;
7032         nudge = 1.0 - 1.0 / (1<<23);
7033         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7034         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7035         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7036         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7037         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7038         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7039         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7040         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7041 #endif
7042
7043
7044
7045 #if 0
7046         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7047         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7048         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7049         r_refdef.view.frustum[0].dist = m[15] - m[12];
7050
7051         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7052         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7053         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7054         r_refdef.view.frustum[1].dist = m[15] + m[12];
7055
7056         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7057         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7058         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7059         r_refdef.view.frustum[2].dist = m[15] - m[13];
7060
7061         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7062         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7063         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7064         r_refdef.view.frustum[3].dist = m[15] + m[13];
7065
7066         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7067         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7068         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7069         r_refdef.view.frustum[4].dist = m[15] - m[14];
7070
7071         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7072         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7073         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7074         r_refdef.view.frustum[5].dist = m[15] + m[14];
7075 #endif
7076
7077         if (r_refdef.view.useperspective)
7078         {
7079                 slopex = 1.0 / r_refdef.view.frustum_x;
7080                 slopey = 1.0 / r_refdef.view.frustum_y;
7081                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7082                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7083                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7084                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7085                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7086
7087                 // Leaving those out was a mistake, those were in the old code, and they
7088                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7089                 // I couldn't reproduce it after adding those normalizations. --blub
7090                 VectorNormalize(r_refdef.view.frustum[0].normal);
7091                 VectorNormalize(r_refdef.view.frustum[1].normal);
7092                 VectorNormalize(r_refdef.view.frustum[2].normal);
7093                 VectorNormalize(r_refdef.view.frustum[3].normal);
7094
7095                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7096                 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]);
7097                 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]);
7098                 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]);
7099                 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]);
7100
7101                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7102                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7103                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7104                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7105                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7106         }
7107         else
7108         {
7109                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7110                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7111                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7112                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7113                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7114                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7115                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7116                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7117                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7118                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7119         }
7120         r_refdef.view.numfrustumplanes = 5;
7121
7122         if (r_refdef.view.useclipplane)
7123         {
7124                 r_refdef.view.numfrustumplanes = 6;
7125                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7126         }
7127
7128         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7129                 PlaneClassify(r_refdef.view.frustum + i);
7130
7131         // LordHavoc: note to all quake engine coders, Quake had a special case
7132         // for 90 degrees which assumed a square view (wrong), so I removed it,
7133         // Quake2 has it disabled as well.
7134
7135         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7136         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7137         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7138         //PlaneClassify(&frustum[0]);
7139
7140         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7141         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7142         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7143         //PlaneClassify(&frustum[1]);
7144
7145         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7146         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7147         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7148         //PlaneClassify(&frustum[2]);
7149
7150         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7151         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7152         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7153         //PlaneClassify(&frustum[3]);
7154
7155         // nearclip plane
7156         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7157         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7158         //PlaneClassify(&frustum[4]);
7159 }
7160
7161 void R_View_Update(void)
7162 {
7163         R_Main_ResizeViewCache();
7164         R_View_SetFrustum();
7165         R_View_WorldVisibility(r_refdef.view.useclipplane);
7166         R_View_UpdateEntityVisible();
7167         R_View_UpdateEntityLighting();
7168 }
7169
7170 void R_SetupView(qboolean allowwaterclippingplane)
7171 {
7172         const float *customclipplane = NULL;
7173         float plane[4];
7174         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7175         {
7176                 // LordHavoc: couldn't figure out how to make this approach the
7177                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7178                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7179                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7180                         dist = r_refdef.view.clipplane.dist;
7181                 plane[0] = r_refdef.view.clipplane.normal[0];
7182                 plane[1] = r_refdef.view.clipplane.normal[1];
7183                 plane[2] = r_refdef.view.clipplane.normal[2];
7184                 plane[3] = dist;
7185                 customclipplane = plane;
7186         }
7187
7188         if (!r_refdef.view.useperspective)
7189                 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);
7190         else if (vid.stencil && r_useinfinitefarclip.integer)
7191                 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);
7192         else
7193                 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);
7194         R_SetViewport(&r_refdef.view.viewport);
7195 }
7196
7197 void R_EntityMatrix(const matrix4x4_t *matrix)
7198 {
7199         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7200         {
7201                 gl_modelmatrixchanged = false;
7202                 gl_modelmatrix = *matrix;
7203                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7204                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7205                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7206                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7207                 CHECKGLERROR
7208                 switch(vid.renderpath)
7209                 {
7210                 case RENDERPATH_GL20:
7211                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7212                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7213                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7214                         break;
7215                 case RENDERPATH_CGGL:
7216 #ifdef SUPPORTCG
7217                         CHECKCGERROR
7218                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7219                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7220                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7221 #endif
7222                         break;
7223                 case RENDERPATH_GL13:
7224                 case RENDERPATH_GL11:
7225                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7226                         break;
7227                 }
7228         }
7229 }
7230
7231 void R_ResetViewRendering2D(void)
7232 {
7233         r_viewport_t viewport;
7234         DrawQ_Finish();
7235
7236         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7237         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);
7238         R_SetViewport(&viewport);
7239         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7240         GL_Color(1, 1, 1, 1);
7241         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7242         GL_BlendFunc(GL_ONE, GL_ZERO);
7243         GL_AlphaTest(false);
7244         GL_ScissorTest(false);
7245         GL_DepthMask(false);
7246         GL_DepthRange(0, 1);
7247         GL_DepthTest(false);
7248         R_EntityMatrix(&identitymatrix);
7249         R_Mesh_ResetTextureState();
7250         GL_PolygonOffset(0, 0);
7251         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7252         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7253         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7254         qglStencilMask(~0);CHECKGLERROR
7255         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7256         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7257         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7258 }
7259
7260 void R_ResetViewRendering3D(void)
7261 {
7262         DrawQ_Finish();
7263
7264         R_SetupView(true);
7265         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7266         GL_Color(1, 1, 1, 1);
7267         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7268         GL_BlendFunc(GL_ONE, GL_ZERO);
7269         GL_AlphaTest(false);
7270         GL_ScissorTest(true);
7271         GL_DepthMask(true);
7272         GL_DepthRange(0, 1);
7273         GL_DepthTest(true);
7274         R_EntityMatrix(&identitymatrix);
7275         R_Mesh_ResetTextureState();
7276         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7277         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7278         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7279         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7280         qglStencilMask(~0);CHECKGLERROR
7281         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7282         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7283         GL_CullFace(r_refdef.view.cullface_back);
7284 }
7285
7286 void R_RenderScene(void);
7287 void R_RenderWaterPlanes(void);
7288
7289 static void R_Water_StartFrame(void)
7290 {
7291         int i;
7292         int waterwidth, waterheight, texturewidth, textureheight;
7293         r_waterstate_waterplane_t *p;
7294
7295         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7296                 return;
7297
7298         switch(vid.renderpath)
7299         {
7300         case RENDERPATH_GL20:
7301         case RENDERPATH_CGGL:
7302                 break;
7303         case RENDERPATH_GL13:
7304         case RENDERPATH_GL11:
7305                 return;
7306         }
7307
7308         // set waterwidth and waterheight to the water resolution that will be
7309         // used (often less than the screen resolution for faster rendering)
7310         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7311         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7312
7313         // calculate desired texture sizes
7314         // can't use water if the card does not support the texture size
7315         if (!r_water.integer || r_showsurfaces.integer)
7316                 texturewidth = textureheight = waterwidth = waterheight = 0;
7317         else if (vid.support.arb_texture_non_power_of_two)
7318         {
7319                 texturewidth = waterwidth;
7320                 textureheight = waterheight;
7321         }
7322         else
7323         {
7324                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7325                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7326         }
7327
7328         // allocate textures as needed
7329         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7330         {
7331                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7332                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7333                 {
7334                         if (p->texture_refraction)
7335                                 R_FreeTexture(p->texture_refraction);
7336                         p->texture_refraction = NULL;
7337                         if (p->texture_reflection)
7338                                 R_FreeTexture(p->texture_reflection);
7339                         p->texture_reflection = NULL;
7340                 }
7341                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7342                 r_waterstate.texturewidth = texturewidth;
7343                 r_waterstate.textureheight = textureheight;
7344         }
7345
7346         if (r_waterstate.texturewidth)
7347         {
7348                 r_waterstate.enabled = true;
7349
7350                 // when doing a reduced render (HDR) we want to use a smaller area
7351                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7352                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7353
7354                 // set up variables that will be used in shader setup
7355                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7356                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7357                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7358                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7359         }
7360
7361         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7362         r_waterstate.numwaterplanes = 0;
7363 }
7364
7365 void R_Water_AddWaterPlane(msurface_t *surface)
7366 {
7367         int triangleindex, planeindex;
7368         const int *e;
7369         vec3_t vert[3];
7370         vec3_t normal;
7371         vec3_t center;
7372         mplane_t plane;
7373         r_waterstate_waterplane_t *p;
7374         texture_t *t = R_GetCurrentTexture(surface->texture);
7375         // just use the first triangle with a valid normal for any decisions
7376         VectorClear(normal);
7377         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7378         {
7379                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7380                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7381                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7382                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7383                 if (VectorLength2(normal) >= 0.001)
7384                         break;
7385         }
7386
7387         VectorCopy(normal, plane.normal);
7388         VectorNormalize(plane.normal);
7389         plane.dist = DotProduct(vert[0], plane.normal);
7390         PlaneClassify(&plane);
7391         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7392         {
7393                 // skip backfaces (except if nocullface is set)
7394                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7395                         return;
7396                 VectorNegate(plane.normal, plane.normal);
7397                 plane.dist *= -1;
7398                 PlaneClassify(&plane);
7399         }
7400
7401
7402         // find a matching plane if there is one
7403         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7404                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7405                         break;
7406         if (planeindex >= r_waterstate.maxwaterplanes)
7407                 return; // nothing we can do, out of planes
7408
7409         // if this triangle does not fit any known plane rendered this frame, add one
7410         if (planeindex >= r_waterstate.numwaterplanes)
7411         {
7412                 // store the new plane
7413                 r_waterstate.numwaterplanes++;
7414                 p->plane = plane;
7415                 // clear materialflags and pvs
7416                 p->materialflags = 0;
7417                 p->pvsvalid = false;
7418         }
7419         // merge this surface's materialflags into the waterplane
7420         p->materialflags |= t->currentmaterialflags;
7421         // merge this surface's PVS into the waterplane
7422         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7423         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7424          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7425         {
7426                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7427                 p->pvsvalid = true;
7428         }
7429 }
7430
7431 static void R_Water_ProcessPlanes(void)
7432 {
7433         r_refdef_view_t originalview;
7434         r_refdef_view_t myview;
7435         int planeindex;
7436         r_waterstate_waterplane_t *p;
7437
7438         originalview = r_refdef.view;
7439
7440         // make sure enough textures are allocated
7441         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7442         {
7443                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7444                 {
7445                         if (!p->texture_refraction)
7446                                 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);
7447                         if (!p->texture_refraction)
7448                                 goto error;
7449                 }
7450
7451                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7452                 {
7453                         if (!p->texture_reflection)
7454                                 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);
7455                         if (!p->texture_reflection)
7456                                 goto error;
7457                 }
7458         }
7459
7460         // render views
7461         r_refdef.view = originalview;
7462         r_refdef.view.showdebug = false;
7463         r_refdef.view.width = r_waterstate.waterwidth;
7464         r_refdef.view.height = r_waterstate.waterheight;
7465         r_refdef.view.useclipplane = true;
7466         myview = r_refdef.view;
7467         r_waterstate.renderingscene = true;
7468         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7469         {
7470                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7471                 {
7472                         r_refdef.view = myview;
7473                         // render reflected scene and copy into texture
7474                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7475                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7476                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7477                         r_refdef.view.clipplane = p->plane;
7478                         // reverse the cullface settings for this render
7479                         r_refdef.view.cullface_front = GL_FRONT;
7480                         r_refdef.view.cullface_back = GL_BACK;
7481                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7482                         {
7483                                 r_refdef.view.usecustompvs = true;
7484                                 if (p->pvsvalid)
7485                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7486                                 else
7487                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7488                         }
7489
7490                         R_ResetViewRendering3D();
7491                         R_ClearScreen(r_refdef.fogenabled);
7492                         R_View_Update();
7493                         R_RenderScene();
7494
7495                         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);
7496                 }
7497
7498                 // render the normal view scene and copy into texture
7499                 // (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)
7500                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7501                 {
7502                         r_waterstate.renderingrefraction = true;
7503                         r_refdef.view = myview;
7504                         r_refdef.view.clipplane = p->plane;
7505                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7506                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7507                         PlaneClassify(&r_refdef.view.clipplane);
7508
7509                         R_ResetViewRendering3D();
7510                         R_ClearScreen(r_refdef.fogenabled);
7511                         R_View_Update();
7512                         R_RenderScene();
7513
7514                         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);
7515                         r_waterstate.renderingrefraction = false;
7516                 }
7517
7518         }
7519         r_waterstate.renderingscene = false;
7520         r_refdef.view = originalview;
7521         R_ResetViewRendering3D();
7522         R_ClearScreen(r_refdef.fogenabled);
7523         R_View_Update();
7524         return;
7525 error:
7526         r_refdef.view = originalview;
7527         r_waterstate.renderingscene = false;
7528         Cvar_SetValueQuick(&r_water, 0);
7529         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7530         return;
7531 }
7532
7533 void R_Bloom_StartFrame(void)
7534 {
7535         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7536
7537         switch(vid.renderpath)
7538         {
7539         case RENDERPATH_GL20:
7540         case RENDERPATH_CGGL:
7541                 break;
7542         case RENDERPATH_GL13:
7543         case RENDERPATH_GL11:
7544                 return;
7545         }
7546
7547         // set bloomwidth and bloomheight to the bloom resolution that will be
7548         // used (often less than the screen resolution for faster rendering)
7549         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7550         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7551         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7552         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7553         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7554
7555         // calculate desired texture sizes
7556         if (vid.support.arb_texture_non_power_of_two)
7557         {
7558                 screentexturewidth = r_refdef.view.width;
7559                 screentextureheight = r_refdef.view.height;
7560                 bloomtexturewidth = r_bloomstate.bloomwidth;
7561                 bloomtextureheight = r_bloomstate.bloomheight;
7562         }
7563         else
7564         {
7565                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7566                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7567                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7568                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7569         }
7570
7571         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))
7572         {
7573                 Cvar_SetValueQuick(&r_hdr, 0);
7574                 Cvar_SetValueQuick(&r_bloom, 0);
7575                 Cvar_SetValueQuick(&r_motionblur, 0);
7576                 Cvar_SetValueQuick(&r_damageblur, 0);
7577         }
7578
7579         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)))
7580                 screentexturewidth = screentextureheight = 0;
7581         if (!r_hdr.integer && !r_bloom.integer)
7582                 bloomtexturewidth = bloomtextureheight = 0;
7583
7584         // allocate textures as needed
7585         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7586         {
7587                 if (r_bloomstate.texture_screen)
7588                         R_FreeTexture(r_bloomstate.texture_screen);
7589                 r_bloomstate.texture_screen = NULL;
7590                 r_bloomstate.screentexturewidth = screentexturewidth;
7591                 r_bloomstate.screentextureheight = screentextureheight;
7592                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7593                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7594         }
7595         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7596         {
7597                 if (r_bloomstate.texture_bloom)
7598                         R_FreeTexture(r_bloomstate.texture_bloom);
7599                 r_bloomstate.texture_bloom = NULL;
7600                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7601                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7602                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7603                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7604         }
7605
7606         // when doing a reduced render (HDR) we want to use a smaller area
7607         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7608         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7609         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7610         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7611         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7612
7613         // set up a texcoord array for the full resolution screen image
7614         // (we have to keep this around to copy back during final render)
7615         r_bloomstate.screentexcoord2f[0] = 0;
7616         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7617         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7618         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7619         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7620         r_bloomstate.screentexcoord2f[5] = 0;
7621         r_bloomstate.screentexcoord2f[6] = 0;
7622         r_bloomstate.screentexcoord2f[7] = 0;
7623
7624         // set up a texcoord array for the reduced resolution bloom image
7625         // (which will be additive blended over the screen image)
7626         r_bloomstate.bloomtexcoord2f[0] = 0;
7627         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7628         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7629         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7630         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7631         r_bloomstate.bloomtexcoord2f[5] = 0;
7632         r_bloomstate.bloomtexcoord2f[6] = 0;
7633         r_bloomstate.bloomtexcoord2f[7] = 0;
7634
7635         if (r_hdr.integer || r_bloom.integer)
7636         {
7637                 r_bloomstate.enabled = true;
7638                 r_bloomstate.hdr = r_hdr.integer != 0;
7639         }
7640
7641         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);
7642 }
7643
7644 void R_Bloom_CopyBloomTexture(float colorscale)
7645 {
7646         r_refdef.stats.bloom++;
7647
7648         // scale down screen texture to the bloom texture size
7649         CHECKGLERROR
7650         R_SetViewport(&r_bloomstate.viewport);
7651         GL_BlendFunc(GL_ONE, GL_ZERO);
7652         GL_Color(colorscale, colorscale, colorscale, 1);
7653         // TODO: optimize with multitexture or GLSL
7654         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7655         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7656         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7657         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7658
7659         // we now have a bloom image in the framebuffer
7660         // copy it into the bloom image texture for later processing
7661         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);
7662         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7663 }
7664
7665 void R_Bloom_CopyHDRTexture(void)
7666 {
7667         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);
7668         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7669 }
7670
7671 void R_Bloom_MakeTexture(void)
7672 {
7673         int x, range, dir;
7674         float xoffset, yoffset, r, brighten;
7675
7676         r_refdef.stats.bloom++;
7677
7678         R_ResetViewRendering2D();
7679         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7680         R_Mesh_ColorPointer(NULL, 0, 0);
7681
7682         // we have a bloom image in the framebuffer
7683         CHECKGLERROR
7684         R_SetViewport(&r_bloomstate.viewport);
7685
7686         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7687         {
7688                 x *= 2;
7689                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7690                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7691                 GL_Color(r, r, r, 1);
7692                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7693                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7694                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7695                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7696
7697                 // copy the vertically blurred bloom view to a texture
7698                 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);
7699                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7700         }
7701
7702         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7703         brighten = r_bloom_brighten.value;
7704         if (r_hdr.integer)
7705                 brighten *= r_hdr_range.value;
7706         brighten = sqrt(brighten);
7707         if(range >= 1)
7708                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7709         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7710         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7711
7712         for (dir = 0;dir < 2;dir++)
7713         {
7714                 // blend on at multiple vertical offsets to achieve a vertical blur
7715                 // TODO: do offset blends using GLSL
7716                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7717                 GL_BlendFunc(GL_ONE, GL_ZERO);
7718                 for (x = -range;x <= range;x++)
7719                 {
7720                         if (!dir){xoffset = 0;yoffset = x;}
7721                         else {xoffset = x;yoffset = 0;}
7722                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7723                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7724                         // compute a texcoord array with the specified x and y offset
7725                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7726                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7727                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7728                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7729                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7730                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7731                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7732                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7733                         // this r value looks like a 'dot' particle, fading sharply to
7734                         // black at the edges
7735                         // (probably not realistic but looks good enough)
7736                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7737                         //r = brighten/(range*2+1);
7738                         r = brighten / (range * 2 + 1);
7739                         if(range >= 1)
7740                                 r *= (1 - x*x/(float)(range*range));
7741                         GL_Color(r, r, r, 1);
7742                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7743                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7744                         GL_BlendFunc(GL_ONE, GL_ONE);
7745                 }
7746
7747                 // copy the vertically blurred bloom view to a texture
7748                 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);
7749                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7750         }
7751
7752         // apply subtract last
7753         // (just like it would be in a GLSL shader)
7754         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7755         {
7756                 GL_BlendFunc(GL_ONE, GL_ZERO);
7757                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7758                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7759                 GL_Color(1, 1, 1, 1);
7760                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7761                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7762
7763                 GL_BlendFunc(GL_ONE, GL_ONE);
7764                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7765                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7766                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7767                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7768                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7769                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7770                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7771
7772                 // copy the darkened bloom view to a texture
7773                 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);
7774                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7775         }
7776 }
7777
7778 void R_HDR_RenderBloomTexture(void)
7779 {
7780         int oldwidth, oldheight;
7781         float oldcolorscale;
7782
7783         oldcolorscale = r_refdef.view.colorscale;
7784         oldwidth = r_refdef.view.width;
7785         oldheight = r_refdef.view.height;
7786         r_refdef.view.width = r_bloomstate.bloomwidth;
7787         r_refdef.view.height = r_bloomstate.bloomheight;
7788
7789         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7790         // TODO: add exposure compensation features
7791         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7792
7793         r_refdef.view.showdebug = false;
7794         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7795
7796         R_ResetViewRendering3D();
7797
7798         R_ClearScreen(r_refdef.fogenabled);
7799         if (r_timereport_active)
7800                 R_TimeReport("HDRclear");
7801
7802         R_View_Update();
7803         if (r_timereport_active)
7804                 R_TimeReport("visibility");
7805
7806         // only do secondary renders with HDR if r_hdr is 2 or higher
7807         r_waterstate.numwaterplanes = 0;
7808         if (r_waterstate.enabled && r_hdr.integer >= 2)
7809                 R_RenderWaterPlanes();
7810
7811         r_refdef.view.showdebug = true;
7812         R_RenderScene();
7813         r_waterstate.numwaterplanes = 0;
7814
7815         R_ResetViewRendering2D();
7816
7817         R_Bloom_CopyHDRTexture();
7818         R_Bloom_MakeTexture();
7819
7820         // restore the view settings
7821         r_refdef.view.width = oldwidth;
7822         r_refdef.view.height = oldheight;
7823         r_refdef.view.colorscale = oldcolorscale;
7824
7825         R_ResetViewRendering3D();
7826
7827         R_ClearScreen(r_refdef.fogenabled);
7828         if (r_timereport_active)
7829                 R_TimeReport("viewclear");
7830 }
7831
7832 static void R_BlendView(void)
7833 {
7834         unsigned int permutation;
7835         float uservecs[4][4];
7836
7837         switch (vid.renderpath)
7838         {
7839         case RENDERPATH_GL20:
7840         case RENDERPATH_CGGL:
7841                 permutation =
7842                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7843                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7844                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7845                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7846                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7847
7848                 if (r_bloomstate.texture_screen)
7849                 {
7850                         // make sure the buffer is available
7851                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7852
7853                         R_ResetViewRendering2D();
7854                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7855                         R_Mesh_ColorPointer(NULL, 0, 0);
7856
7857                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7858                         {
7859                                 // declare variables
7860                                 float speed;
7861                                 static float avgspeed;
7862
7863                                 speed = VectorLength(cl.movement_velocity);
7864
7865                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7866                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7867
7868                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7869                                 speed = bound(0, speed, 1);
7870                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7871
7872                                 // calculate values into a standard alpha
7873                                 cl.motionbluralpha = 1 - exp(-
7874                                                 (
7875                                                  (r_motionblur.value * speed / 80)
7876                                                  +
7877                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7878                                                 )
7879                                                 /
7880                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7881                                            );
7882
7883                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7884                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7885                                 // apply the blur
7886                                 if (cl.motionbluralpha > 0)
7887                                 {
7888                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7889                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7890                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7891                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7892                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7893                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7894                                 }
7895                         }
7896
7897                         // copy view into the screen texture
7898                         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);
7899                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7900                 }
7901                 else if (!r_bloomstate.texture_bloom)
7902                 {
7903                         // we may still have to do view tint...
7904                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7905                         {
7906                                 // apply a color tint to the whole view
7907                                 R_ResetViewRendering2D();
7908                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7909                                 R_Mesh_ColorPointer(NULL, 0, 0);
7910                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7911                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7912                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7913                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7914                         }
7915                         break; // no screen processing, no bloom, skip it
7916                 }
7917
7918                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7919                 {
7920                         // render simple bloom effect
7921                         // copy the screen and shrink it and darken it for the bloom process
7922                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7923                         // make the bloom texture
7924                         R_Bloom_MakeTexture();
7925                 }
7926
7927 #if _MSC_VER >= 1400
7928 #define sscanf sscanf_s
7929 #endif
7930                 memset(uservecs, 0, sizeof(uservecs));
7931                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7932                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7933                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7934                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7935
7936                 R_ResetViewRendering2D();
7937                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7938                 R_Mesh_ColorPointer(NULL, 0, 0);
7939                 GL_Color(1, 1, 1, 1);
7940                 GL_BlendFunc(GL_ONE, GL_ZERO);
7941                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7942                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7943
7944                 switch(vid.renderpath)
7945                 {
7946                 case RENDERPATH_GL20:
7947                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7948                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7949                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7950                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7951                         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]);
7952                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7953                         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]);
7954                         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]);
7955                         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]);
7956                         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]);
7957                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7958                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7959                         break;
7960                 case RENDERPATH_CGGL:
7961 #ifdef SUPPORTCG
7962                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7963                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7964                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7965                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7966                         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
7967                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7968                         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
7969                         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
7970                         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
7971                         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
7972                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7973                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7974 #endif
7975                         break;
7976                 default:
7977                         break;
7978                 }
7979                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7980                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7981                 break;
7982         case RENDERPATH_GL13:
7983         case RENDERPATH_GL11:
7984                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7985                 {
7986                         // apply a color tint to the whole view
7987                         R_ResetViewRendering2D();
7988                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7989                         R_Mesh_ColorPointer(NULL, 0, 0);
7990                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7991                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7992                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7993                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7994                 }
7995                 break;
7996         }
7997 }
7998
7999 matrix4x4_t r_waterscrollmatrix;
8000
8001 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8002 {
8003         if (r_refdef.fog_density)
8004         {
8005                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8006                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8007                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8008
8009                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8010                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8011                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8012                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8013
8014                 {
8015                         vec3_t fogvec;
8016                         VectorCopy(r_refdef.fogcolor, fogvec);
8017                         //   color.rgb *= ContrastBoost * SceneBrightness;
8018                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8019                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8020                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8021                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8022                 }
8023         }
8024 }
8025
8026 void R_UpdateVariables(void)
8027 {
8028         R_Textures_Frame();
8029
8030         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8031
8032         r_refdef.farclip = r_farclip_base.value;
8033         if (r_refdef.scene.worldmodel)
8034                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8035         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8036
8037         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8038                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8039         r_refdef.polygonfactor = 0;
8040         r_refdef.polygonoffset = 0;
8041         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8042         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8043
8044         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8045         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8046         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8047         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8048         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8049         if (r_showsurfaces.integer)
8050         {
8051                 r_refdef.scene.rtworld = false;
8052                 r_refdef.scene.rtworldshadows = false;
8053                 r_refdef.scene.rtdlight = false;
8054                 r_refdef.scene.rtdlightshadows = false;
8055                 r_refdef.lightmapintensity = 0;
8056         }
8057
8058         if (gamemode == GAME_NEHAHRA)
8059         {
8060                 if (gl_fogenable.integer)
8061                 {
8062                         r_refdef.oldgl_fogenable = true;
8063                         r_refdef.fog_density = gl_fogdensity.value;
8064                         r_refdef.fog_red = gl_fogred.value;
8065                         r_refdef.fog_green = gl_foggreen.value;
8066                         r_refdef.fog_blue = gl_fogblue.value;
8067                         r_refdef.fog_alpha = 1;
8068                         r_refdef.fog_start = 0;
8069                         r_refdef.fog_end = gl_skyclip.value;
8070                         r_refdef.fog_height = 1<<30;
8071                         r_refdef.fog_fadedepth = 128;
8072                 }
8073                 else if (r_refdef.oldgl_fogenable)
8074                 {
8075                         r_refdef.oldgl_fogenable = false;
8076                         r_refdef.fog_density = 0;
8077                         r_refdef.fog_red = 0;
8078                         r_refdef.fog_green = 0;
8079                         r_refdef.fog_blue = 0;
8080                         r_refdef.fog_alpha = 0;
8081                         r_refdef.fog_start = 0;
8082                         r_refdef.fog_end = 0;
8083                         r_refdef.fog_height = 1<<30;
8084                         r_refdef.fog_fadedepth = 128;
8085                 }
8086         }
8087
8088         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8089         r_refdef.fog_start = max(0, r_refdef.fog_start);
8090         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8091
8092         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8093
8094         if (r_refdef.fog_density && r_drawfog.integer)
8095         {
8096                 r_refdef.fogenabled = true;
8097                 // this is the point where the fog reaches 0.9986 alpha, which we
8098                 // consider a good enough cutoff point for the texture
8099                 // (0.9986 * 256 == 255.6)
8100                 if (r_fog_exp2.integer)
8101                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8102                 else
8103                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8104                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8105                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8106                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8107                 // fog color was already set
8108                 // update the fog texture
8109                 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)
8110                         R_BuildFogTexture();
8111         }
8112         else
8113                 r_refdef.fogenabled = false;
8114
8115         switch(vid.renderpath)
8116         {
8117         case RENDERPATH_GL20:
8118         case RENDERPATH_CGGL:
8119                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8120                 {
8121                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8122                         {
8123                                 // build GLSL gamma texture
8124 #define RAMPWIDTH 256
8125                                 unsigned short ramp[RAMPWIDTH * 3];
8126                                 unsigned char rampbgr[RAMPWIDTH][4];
8127                                 int i;
8128
8129                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8130
8131                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8132                                 for(i = 0; i < RAMPWIDTH; ++i)
8133                                 {
8134                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8135                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8136                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8137                                         rampbgr[i][3] = 0;
8138                                 }
8139                                 if (r_texture_gammaramps)
8140                                 {
8141                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8142                                 }
8143                                 else
8144                                 {
8145                                         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);
8146                                 }
8147                         }
8148                 }
8149                 else
8150                 {
8151                         // remove GLSL gamma texture
8152                 }
8153                 break;
8154         case RENDERPATH_GL13:
8155         case RENDERPATH_GL11:
8156                 break;
8157         }
8158 }
8159
8160 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8161 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8162 /*
8163 ================
8164 R_SelectScene
8165 ================
8166 */
8167 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8168         if( scenetype != r_currentscenetype ) {
8169                 // store the old scenetype
8170                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8171                 r_currentscenetype = scenetype;
8172                 // move in the new scene
8173                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8174         }
8175 }
8176
8177 /*
8178 ================
8179 R_GetScenePointer
8180 ================
8181 */
8182 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8183 {
8184         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8185         if( scenetype == r_currentscenetype ) {
8186                 return &r_refdef.scene;
8187         } else {
8188                 return &r_scenes_store[ scenetype ];
8189         }
8190 }
8191
8192 /*
8193 ================
8194 R_RenderView
8195 ================
8196 */
8197 void R_RenderView(void)
8198 {
8199         if (r_timereport_active)
8200                 R_TimeReport("start");
8201         r_textureframe++; // used only by R_GetCurrentTexture
8202         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8203
8204         if (!r_drawentities.integer)
8205                 r_refdef.scene.numentities = 0;
8206
8207         R_AnimCache_ClearCache();
8208         R_FrameData_NewFrame();
8209
8210         if (r_refdef.view.isoverlay)
8211         {
8212                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8213                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8214                 R_TimeReport("depthclear");
8215
8216                 r_refdef.view.showdebug = false;
8217
8218                 r_waterstate.enabled = false;
8219                 r_waterstate.numwaterplanes = 0;
8220
8221                 R_RenderScene();
8222
8223                 CHECKGLERROR
8224                 return;
8225         }
8226
8227         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8228                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8229
8230         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8231
8232         // break apart the view matrix into vectors for various purposes
8233         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8234         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8235         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8236         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8237         // make an inverted copy of the view matrix for tracking sprites
8238         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8239
8240         R_Shadow_UpdateWorldLightSelection();
8241
8242         R_Bloom_StartFrame();
8243         R_Water_StartFrame();
8244
8245         CHECKGLERROR
8246         if (r_timereport_active)
8247                 R_TimeReport("viewsetup");
8248
8249         R_ResetViewRendering3D();
8250
8251         if (r_refdef.view.clear || r_refdef.fogenabled)
8252         {
8253                 R_ClearScreen(r_refdef.fogenabled);
8254                 if (r_timereport_active)
8255                         R_TimeReport("viewclear");
8256         }
8257         r_refdef.view.clear = true;
8258
8259         // this produces a bloom texture to be used in R_BlendView() later
8260         if (r_hdr.integer && r_bloomstate.bloomwidth)
8261         {
8262                 R_HDR_RenderBloomTexture();
8263                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8264                 r_textureframe++; // used only by R_GetCurrentTexture
8265         }
8266
8267         r_refdef.view.showdebug = true;
8268
8269         R_View_Update();
8270         if (r_timereport_active)
8271                 R_TimeReport("visibility");
8272
8273         r_waterstate.numwaterplanes = 0;
8274         if (r_waterstate.enabled)
8275                 R_RenderWaterPlanes();
8276
8277         R_RenderScene();
8278         r_waterstate.numwaterplanes = 0;
8279
8280         R_BlendView();
8281         if (r_timereport_active)
8282                 R_TimeReport("blendview");
8283
8284         GL_Scissor(0, 0, vid.width, vid.height);
8285         GL_ScissorTest(false);
8286         CHECKGLERROR
8287 }
8288
8289 void R_RenderWaterPlanes(void)
8290 {
8291         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8292         {
8293                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8294                 if (r_timereport_active)
8295                         R_TimeReport("waterworld");
8296         }
8297
8298         // don't let sound skip if going slow
8299         if (r_refdef.scene.extraupdate)
8300                 S_ExtraUpdate ();
8301
8302         R_DrawModelsAddWaterPlanes();
8303         if (r_timereport_active)
8304                 R_TimeReport("watermodels");
8305
8306         if (r_waterstate.numwaterplanes)
8307         {
8308                 R_Water_ProcessPlanes();
8309                 if (r_timereport_active)
8310                         R_TimeReport("waterscenes");
8311         }
8312 }
8313
8314 extern void R_DrawLightningBeams (void);
8315 extern void VM_CL_AddPolygonsToMeshQueue (void);
8316 extern void R_DrawPortals (void);
8317 extern cvar_t cl_locs_show;
8318 static void R_DrawLocs(void);
8319 static void R_DrawEntityBBoxes(void);
8320 static void R_DrawModelDecals(void);
8321 extern void R_DrawModelShadows(void);
8322 extern void R_DrawModelShadowMaps(void);
8323 extern cvar_t cl_decals_newsystem;
8324 extern qboolean r_shadow_usingdeferredprepass;
8325 void R_RenderScene(void)
8326 {
8327         qboolean shadowmapping = false;
8328
8329         r_refdef.stats.renders++;
8330
8331         R_UpdateFogColor();
8332
8333         // don't let sound skip if going slow
8334         if (r_refdef.scene.extraupdate)
8335                 S_ExtraUpdate ();
8336
8337         R_MeshQueue_BeginScene();
8338
8339         R_SkyStartFrame();
8340
8341         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);
8342
8343         if (cl.csqc_vidvars.drawworld)
8344         {
8345                 // don't let sound skip if going slow
8346                 if (r_refdef.scene.extraupdate)
8347                         S_ExtraUpdate ();
8348
8349                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8350                 {
8351                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8352                         if (r_timereport_active)
8353                                 R_TimeReport("worldsky");
8354                 }
8355
8356                 if (R_DrawBrushModelsSky() && r_timereport_active)
8357                         R_TimeReport("bmodelsky");
8358
8359                 if (skyrendermasked && skyrenderlater)
8360                 {
8361                         // we have to force off the water clipping plane while rendering sky
8362                         R_SetupView(false);
8363                         R_Sky();
8364                         R_SetupView(true);
8365                         if (r_timereport_active)
8366                                 R_TimeReport("sky");
8367                 }
8368         }
8369
8370         R_AnimCache_CacheVisibleEntities();
8371         if (r_timereport_active)
8372                 R_TimeReport("animation");
8373
8374         R_Shadow_PrepareLights();
8375         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8376                 R_Shadow_PrepareModelShadows();
8377         if (r_timereport_active)
8378                 R_TimeReport("preparelights");
8379
8380         if (R_Shadow_ShadowMappingEnabled())
8381                 shadowmapping = true;
8382
8383         if (r_shadow_usingdeferredprepass)
8384                 R_Shadow_DrawPrepass();
8385
8386         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8387         {
8388                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8389                 if (r_timereport_active)
8390                         R_TimeReport("worlddepth");
8391         }
8392         if (r_depthfirst.integer >= 2)
8393         {
8394                 R_DrawModelsDepth();
8395                 if (r_timereport_active)
8396                         R_TimeReport("modeldepth");
8397         }
8398
8399         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8400         {
8401                 R_DrawModelShadowMaps();
8402                 R_ResetViewRendering3D();
8403                 // don't let sound skip if going slow
8404                 if (r_refdef.scene.extraupdate)
8405                         S_ExtraUpdate ();
8406         }
8407
8408         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8409         {
8410                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8411                 if (r_timereport_active)
8412                         R_TimeReport("world");
8413         }
8414
8415         // don't let sound skip if going slow
8416         if (r_refdef.scene.extraupdate)
8417                 S_ExtraUpdate ();
8418
8419         R_DrawModels();
8420         if (r_timereport_active)
8421                 R_TimeReport("models");
8422
8423         // don't let sound skip if going slow
8424         if (r_refdef.scene.extraupdate)
8425                 S_ExtraUpdate ();
8426
8427         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8428         {
8429                 R_DrawModelShadows();
8430                 R_ResetViewRendering3D();
8431                 // don't let sound skip if going slow
8432                 if (r_refdef.scene.extraupdate)
8433                         S_ExtraUpdate ();
8434         }
8435
8436         if (!r_shadow_usingdeferredprepass)
8437         {
8438                 R_Shadow_DrawLights();
8439                 if (r_timereport_active)
8440                         R_TimeReport("rtlights");
8441         }
8442
8443         // don't let sound skip if going slow
8444         if (r_refdef.scene.extraupdate)
8445                 S_ExtraUpdate ();
8446
8447         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8448         {
8449                 R_DrawModelShadows();
8450                 R_ResetViewRendering3D();
8451                 // don't let sound skip if going slow
8452                 if (r_refdef.scene.extraupdate)
8453                         S_ExtraUpdate ();
8454         }
8455
8456         if (cl.csqc_vidvars.drawworld)
8457         {
8458                 if (cl_decals_newsystem.integer)
8459                 {
8460                         R_DrawModelDecals();
8461                         if (r_timereport_active)
8462                                 R_TimeReport("modeldecals");
8463                 }
8464                 else
8465                 {
8466                         R_DrawDecals();
8467                         if (r_timereport_active)
8468                                 R_TimeReport("decals");
8469                 }
8470
8471                 R_DrawParticles();
8472                 if (r_timereport_active)
8473                         R_TimeReport("particles");
8474
8475                 R_DrawExplosions();
8476                 if (r_timereport_active)
8477                         R_TimeReport("explosions");
8478
8479                 R_DrawLightningBeams();
8480                 if (r_timereport_active)
8481                         R_TimeReport("lightning");
8482         }
8483
8484         VM_CL_AddPolygonsToMeshQueue();
8485
8486         if (r_refdef.view.showdebug)
8487         {
8488                 if (cl_locs_show.integer)
8489                 {
8490                         R_DrawLocs();
8491                         if (r_timereport_active)
8492                                 R_TimeReport("showlocs");
8493                 }
8494
8495                 if (r_drawportals.integer)
8496                 {
8497                         R_DrawPortals();
8498                         if (r_timereport_active)
8499                                 R_TimeReport("portals");
8500                 }
8501
8502                 if (r_showbboxes.value > 0)
8503                 {
8504                         R_DrawEntityBBoxes();
8505                         if (r_timereport_active)
8506                                 R_TimeReport("bboxes");
8507                 }
8508         }
8509
8510         R_MeshQueue_RenderTransparent();
8511         if (r_timereport_active)
8512                 R_TimeReport("drawtrans");
8513
8514         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))
8515         {
8516                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8517                 if (r_timereport_active)
8518                         R_TimeReport("worlddebug");
8519                 R_DrawModelsDebug();
8520                 if (r_timereport_active)
8521                         R_TimeReport("modeldebug");
8522         }
8523
8524         if (cl.csqc_vidvars.drawworld)
8525         {
8526                 R_Shadow_DrawCoronas();
8527                 if (r_timereport_active)
8528                         R_TimeReport("coronas");
8529         }
8530
8531         // don't let sound skip if going slow
8532         if (r_refdef.scene.extraupdate)
8533                 S_ExtraUpdate ();
8534
8535         R_ResetViewRendering2D();
8536 }
8537
8538 static const unsigned short bboxelements[36] =
8539 {
8540         5, 1, 3, 5, 3, 7,
8541         6, 2, 0, 6, 0, 4,
8542         7, 3, 2, 7, 2, 6,
8543         4, 0, 1, 4, 1, 5,
8544         4, 5, 7, 4, 7, 6,
8545         1, 0, 2, 1, 2, 3,
8546 };
8547
8548 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8549 {
8550         int i;
8551         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8552
8553         RSurf_ActiveWorldEntity();
8554
8555         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8556         GL_DepthMask(false);
8557         GL_DepthRange(0, 1);
8558         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8559         R_Mesh_ResetTextureState();
8560
8561         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8562         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8563         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8564         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8565         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8566         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8567         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8568         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8569         R_FillColors(color4f, 8, cr, cg, cb, ca);
8570         if (r_refdef.fogenabled)
8571         {
8572                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8573                 {
8574                         f1 = RSurf_FogVertex(v);
8575                         f2 = 1 - f1;
8576                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8577                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8578                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8579                 }
8580         }
8581         R_Mesh_VertexPointer(vertex3f, 0, 0);
8582         R_Mesh_ColorPointer(color4f, 0, 0);
8583         R_Mesh_ResetTextureState();
8584         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8585         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8586 }
8587
8588 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8589 {
8590         int i;
8591         float color[4];
8592         prvm_edict_t *edict;
8593         prvm_prog_t *prog_save = prog;
8594
8595         // this function draws bounding boxes of server entities
8596         if (!sv.active)
8597                 return;
8598
8599         GL_CullFace(GL_NONE);
8600         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8601
8602         prog = 0;
8603         SV_VM_Begin();
8604         for (i = 0;i < numsurfaces;i++)
8605         {
8606                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8607                 switch ((int)edict->fields.server->solid)
8608                 {
8609                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8610                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8611                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8612                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8613                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8614                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8615                 }
8616                 color[3] *= r_showbboxes.value;
8617                 color[3] = bound(0, color[3], 1);
8618                 GL_DepthTest(!r_showdisabledepthtest.integer);
8619                 GL_CullFace(r_refdef.view.cullface_front);
8620                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8621         }
8622         SV_VM_End();
8623         prog = prog_save;
8624 }
8625
8626 static void R_DrawEntityBBoxes(void)
8627 {
8628         int i;
8629         prvm_edict_t *edict;
8630         vec3_t center;
8631         prvm_prog_t *prog_save = prog;
8632
8633         // this function draws bounding boxes of server entities
8634         if (!sv.active)
8635                 return;
8636
8637         prog = 0;
8638         SV_VM_Begin();
8639         for (i = 0;i < prog->num_edicts;i++)
8640         {
8641                 edict = PRVM_EDICT_NUM(i);
8642                 if (edict->priv.server->free)
8643                         continue;
8644                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8645                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8646                         continue;
8647                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8648                         continue;
8649                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8650                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8651         }
8652         SV_VM_End();
8653         prog = prog_save;
8654 }
8655
8656 static const int nomodelelement3i[24] =
8657 {
8658         5, 2, 0,
8659         5, 1, 2,
8660         5, 0, 3,
8661         5, 3, 1,
8662         0, 2, 4,
8663         2, 1, 4,
8664         3, 0, 4,
8665         1, 3, 4
8666 };
8667
8668 static const unsigned short nomodelelement3s[24] =
8669 {
8670         5, 2, 0,
8671         5, 1, 2,
8672         5, 0, 3,
8673         5, 3, 1,
8674         0, 2, 4,
8675         2, 1, 4,
8676         3, 0, 4,
8677         1, 3, 4
8678 };
8679
8680 static const float nomodelvertex3f[6*3] =
8681 {
8682         -16,   0,   0,
8683          16,   0,   0,
8684           0, -16,   0,
8685           0,  16,   0,
8686           0,   0, -16,
8687           0,   0,  16
8688 };
8689
8690 static const float nomodelcolor4f[6*4] =
8691 {
8692         0.0f, 0.0f, 0.5f, 1.0f,
8693         0.0f, 0.0f, 0.5f, 1.0f,
8694         0.0f, 0.5f, 0.0f, 1.0f,
8695         0.0f, 0.5f, 0.0f, 1.0f,
8696         0.5f, 0.0f, 0.0f, 1.0f,
8697         0.5f, 0.0f, 0.0f, 1.0f
8698 };
8699
8700 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8701 {
8702         int i;
8703         float f1, f2, *c;
8704         float color4f[6*4];
8705
8706         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);
8707
8708         // this is only called once per entity so numsurfaces is always 1, and
8709         // surfacelist is always {0}, so this code does not handle batches
8710
8711         if (rsurface.ent_flags & RENDER_ADDITIVE)
8712         {
8713                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8714                 GL_DepthMask(false);
8715         }
8716         else if (rsurface.colormod[3] < 1)
8717         {
8718                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8719                 GL_DepthMask(false);
8720         }
8721         else
8722         {
8723                 GL_BlendFunc(GL_ONE, GL_ZERO);
8724                 GL_DepthMask(true);
8725         }
8726         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8727         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8728         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8729         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8730         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8731         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8732         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8733         R_Mesh_ColorPointer(color4f, 0, 0);
8734         for (i = 0, c = color4f;i < 6;i++, c += 4)
8735         {
8736                 c[0] *= rsurface.colormod[0];
8737                 c[1] *= rsurface.colormod[1];
8738                 c[2] *= rsurface.colormod[2];
8739                 c[3] *= rsurface.colormod[3];
8740         }
8741         if (r_refdef.fogenabled)
8742         {
8743                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8744                 {
8745                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8746                         f2 = 1 - f1;
8747                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8748                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8749                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8750                 }
8751         }
8752         R_Mesh_ResetTextureState();
8753         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8754 }
8755
8756 void R_DrawNoModel(entity_render_t *ent)
8757 {
8758         vec3_t org;
8759         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8760         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8761                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8762         else
8763                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8764 }
8765
8766 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8767 {
8768         vec3_t right1, right2, diff, normal;
8769
8770         VectorSubtract (org2, org1, normal);
8771
8772         // calculate 'right' vector for start
8773         VectorSubtract (r_refdef.view.origin, org1, diff);
8774         CrossProduct (normal, diff, right1);
8775         VectorNormalize (right1);
8776
8777         // calculate 'right' vector for end
8778         VectorSubtract (r_refdef.view.origin, org2, diff);
8779         CrossProduct (normal, diff, right2);
8780         VectorNormalize (right2);
8781
8782         vert[ 0] = org1[0] + width * right1[0];
8783         vert[ 1] = org1[1] + width * right1[1];
8784         vert[ 2] = org1[2] + width * right1[2];
8785         vert[ 3] = org1[0] - width * right1[0];
8786         vert[ 4] = org1[1] - width * right1[1];
8787         vert[ 5] = org1[2] - width * right1[2];
8788         vert[ 6] = org2[0] - width * right2[0];
8789         vert[ 7] = org2[1] - width * right2[1];
8790         vert[ 8] = org2[2] - width * right2[2];
8791         vert[ 9] = org2[0] + width * right2[0];
8792         vert[10] = org2[1] + width * right2[1];
8793         vert[11] = org2[2] + width * right2[2];
8794 }
8795
8796 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)
8797 {
8798         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8799         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8800         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8801         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8802         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8803         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8804         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8805         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8806         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8807         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8808         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8809         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8810 }
8811
8812 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8813 {
8814         int i;
8815         float *vertex3f;
8816         float v[3];
8817         VectorSet(v, x, y, z);
8818         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8819                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8820                         break;
8821         if (i == mesh->numvertices)
8822         {
8823                 if (mesh->numvertices < mesh->maxvertices)
8824                 {
8825                         VectorCopy(v, vertex3f);
8826                         mesh->numvertices++;
8827                 }
8828                 return mesh->numvertices;
8829         }
8830         else
8831                 return i;
8832 }
8833
8834 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8835 {
8836         int i;
8837         int *e, element[3];
8838         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8839         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8840         e = mesh->element3i + mesh->numtriangles * 3;
8841         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8842         {
8843                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8844                 if (mesh->numtriangles < mesh->maxtriangles)
8845                 {
8846                         *e++ = element[0];
8847                         *e++ = element[1];
8848                         *e++ = element[2];
8849                         mesh->numtriangles++;
8850                 }
8851                 element[1] = element[2];
8852         }
8853 }
8854
8855 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8856 {
8857         int i;
8858         int *e, element[3];
8859         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8860         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8861         e = mesh->element3i + mesh->numtriangles * 3;
8862         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8863         {
8864                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8865                 if (mesh->numtriangles < mesh->maxtriangles)
8866                 {
8867                         *e++ = element[0];
8868                         *e++ = element[1];
8869                         *e++ = element[2];
8870                         mesh->numtriangles++;
8871                 }
8872                 element[1] = element[2];
8873         }
8874 }
8875
8876 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8877 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8878 {
8879         int planenum, planenum2;
8880         int w;
8881         int tempnumpoints;
8882         mplane_t *plane, *plane2;
8883         double maxdist;
8884         double temppoints[2][256*3];
8885         // figure out how large a bounding box we need to properly compute this brush
8886         maxdist = 0;
8887         for (w = 0;w < numplanes;w++)
8888                 maxdist = max(maxdist, fabs(planes[w].dist));
8889         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8890         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8891         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8892         {
8893                 w = 0;
8894                 tempnumpoints = 4;
8895                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8896                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8897                 {
8898                         if (planenum2 == planenum)
8899                                 continue;
8900                         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);
8901                         w = !w;
8902                 }
8903                 if (tempnumpoints < 3)
8904                         continue;
8905                 // generate elements forming a triangle fan for this polygon
8906                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8907         }
8908 }
8909
8910 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)
8911 {
8912         texturelayer_t *layer;
8913         layer = t->currentlayers + t->currentnumlayers++;
8914         layer->type = type;
8915         layer->depthmask = depthmask;
8916         layer->blendfunc1 = blendfunc1;
8917         layer->blendfunc2 = blendfunc2;
8918         layer->texture = texture;
8919         layer->texmatrix = *matrix;
8920         layer->color[0] = r;
8921         layer->color[1] = g;
8922         layer->color[2] = b;
8923         layer->color[3] = a;
8924 }
8925
8926 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8927 {
8928         double index, f;
8929         index = parms[2] + r_refdef.scene.time * parms[3];
8930         index -= floor(index);
8931         switch (func)
8932         {
8933         default:
8934         case Q3WAVEFUNC_NONE:
8935         case Q3WAVEFUNC_NOISE:
8936         case Q3WAVEFUNC_COUNT:
8937                 f = 0;
8938                 break;
8939         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8940         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8941         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8942         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8943         case Q3WAVEFUNC_TRIANGLE:
8944                 index *= 4;
8945                 f = index - floor(index);
8946                 if (index < 1)
8947                         f = f;
8948                 else if (index < 2)
8949                         f = 1 - f;
8950                 else if (index < 3)
8951                         f = -f;
8952                 else
8953                         f = -(1 - f);
8954                 break;
8955         }
8956         return (float)(parms[0] + parms[1] * f);
8957 }
8958
8959 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8960 {
8961         int w, h, idx;
8962         float f;
8963         float tcmat[12];
8964         matrix4x4_t matrix, temp;
8965         switch(tcmod->tcmod)
8966         {
8967                 case Q3TCMOD_COUNT:
8968                 case Q3TCMOD_NONE:
8969                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8970                                 matrix = r_waterscrollmatrix;
8971                         else
8972                                 matrix = identitymatrix;
8973                         break;
8974                 case Q3TCMOD_ENTITYTRANSLATE:
8975                         // this is used in Q3 to allow the gamecode to control texcoord
8976                         // scrolling on the entity, which is not supported in darkplaces yet.
8977                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8978                         break;
8979                 case Q3TCMOD_ROTATE:
8980                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8981                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8982                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8983                         break;
8984                 case Q3TCMOD_SCALE:
8985                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8986                         break;
8987                 case Q3TCMOD_SCROLL:
8988                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8989                         break;
8990                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8991                         w = (int) tcmod->parms[0];
8992                         h = (int) tcmod->parms[1];
8993                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8994                         f = f - floor(f);
8995                         idx = (int) floor(f * w * h);
8996                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8997                         break;
8998                 case Q3TCMOD_STRETCH:
8999                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9000                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9001                         break;
9002                 case Q3TCMOD_TRANSFORM:
9003                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9004                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9005                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9006                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9007                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9008                         break;
9009                 case Q3TCMOD_TURBULENT:
9010                         // this is handled in the RSurf_PrepareVertices function
9011                         matrix = identitymatrix;
9012                         break;
9013         }
9014         temp = *texmatrix;
9015         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9016 }
9017
9018 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9019 {
9020         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9021         char name[MAX_QPATH];
9022         skinframe_t *skinframe;
9023         unsigned char pixels[296*194];
9024         strlcpy(cache->name, skinname, sizeof(cache->name));
9025         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9026         if (developer_loading.integer)
9027                 Con_Printf("loading %s\n", name);
9028         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9029         if (!skinframe || !skinframe->base)
9030         {
9031                 unsigned char *f;
9032                 fs_offset_t filesize;
9033                 skinframe = NULL;
9034                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9035                 if (f)
9036                 {
9037                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9038                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9039                         Mem_Free(f);
9040                 }
9041         }
9042         cache->skinframe = skinframe;
9043 }
9044
9045 texture_t *R_GetCurrentTexture(texture_t *t)
9046 {
9047         int i;
9048         const entity_render_t *ent = rsurface.entity;
9049         dp_model_t *model = ent->model;
9050         q3shaderinfo_layer_tcmod_t *tcmod;
9051
9052         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9053                 return t->currentframe;
9054         t->update_lastrenderframe = r_textureframe;
9055         t->update_lastrenderentity = (void *)ent;
9056
9057         // switch to an alternate material if this is a q1bsp animated material
9058         {
9059                 texture_t *texture = t;
9060                 int s = rsurface.ent_skinnum;
9061                 if ((unsigned int)s >= (unsigned int)model->numskins)
9062                         s = 0;
9063                 if (model->skinscenes)
9064                 {
9065                         if (model->skinscenes[s].framecount > 1)
9066                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9067                         else
9068                                 s = model->skinscenes[s].firstframe;
9069                 }
9070                 if (s > 0)
9071                         t = t + s * model->num_surfaces;
9072                 if (t->animated)
9073                 {
9074                         // use an alternate animation if the entity's frame is not 0,
9075                         // and only if the texture has an alternate animation
9076                         if (rsurface.ent_alttextures && t->anim_total[1])
9077                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9078                         else
9079                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9080                 }
9081                 texture->currentframe = t;
9082         }
9083
9084         // update currentskinframe to be a qw skin or animation frame
9085         if (rsurface.ent_qwskin >= 0)
9086         {
9087                 i = rsurface.ent_qwskin;
9088                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9089                 {
9090                         r_qwskincache_size = cl.maxclients;
9091                         if (r_qwskincache)
9092                                 Mem_Free(r_qwskincache);
9093                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9094                 }
9095                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9096                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9097                 t->currentskinframe = r_qwskincache[i].skinframe;
9098                 if (t->currentskinframe == NULL)
9099                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9100         }
9101         else if (t->numskinframes >= 2)
9102                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9103         if (t->backgroundnumskinframes >= 2)
9104                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9105
9106         t->currentmaterialflags = t->basematerialflags;
9107         t->currentalpha = rsurface.colormod[3];
9108         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9109                 t->currentalpha *= r_wateralpha.value;
9110         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9111                 t->currentalpha *= t->r_water_wateralpha;
9112         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9113                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9114         if (!(rsurface.ent_flags & RENDER_LIGHT))
9115                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9116         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9117         {
9118                 // pick a model lighting mode
9119                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9120                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9121                 else
9122                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9123         }
9124         if (rsurface.ent_flags & RENDER_ADDITIVE)
9125                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9126         else if (t->currentalpha < 1)
9127                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9128         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9129                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9130         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9131                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9132         if (t->backgroundnumskinframes)
9133                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9134         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9135         {
9136                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9137                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9138         }
9139         else
9140                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9141         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9142                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9143
9144         // there is no tcmod
9145         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9146         {
9147                 t->currenttexmatrix = r_waterscrollmatrix;
9148                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9149         }
9150         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9151         {
9152                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9153                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9154         }
9155
9156         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9157                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9158         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9159                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9160
9161         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9162         if (t->currentskinframe->qpixels)
9163                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9164         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9165         if (!t->basetexture)
9166                 t->basetexture = r_texture_notexture;
9167         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9168         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9169         t->nmaptexture = t->currentskinframe->nmap;
9170         if (!t->nmaptexture)
9171                 t->nmaptexture = r_texture_blanknormalmap;
9172         t->glosstexture = r_texture_black;
9173         t->glowtexture = t->currentskinframe->glow;
9174         t->fogtexture = t->currentskinframe->fog;
9175         t->reflectmasktexture = t->currentskinframe->reflect;
9176         if (t->backgroundnumskinframes)
9177         {
9178                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9179                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9180                 t->backgroundglosstexture = r_texture_black;
9181                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9182                 if (!t->backgroundnmaptexture)
9183                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9184         }
9185         else
9186         {
9187                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9188                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9189                 t->backgroundglosstexture = r_texture_black;
9190                 t->backgroundglowtexture = NULL;
9191         }
9192         t->specularpower = r_shadow_glossexponent.value;
9193         // TODO: store reference values for these in the texture?
9194         t->specularscale = 0;
9195         if (r_shadow_gloss.integer > 0)
9196         {
9197                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9198                 {
9199                         if (r_shadow_glossintensity.value > 0)
9200                         {
9201                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9202                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9203                                 t->specularscale = r_shadow_glossintensity.value;
9204                         }
9205                 }
9206                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9207                 {
9208                         t->glosstexture = r_texture_white;
9209                         t->backgroundglosstexture = r_texture_white;
9210                         t->specularscale = r_shadow_gloss2intensity.value;
9211                         t->specularpower = r_shadow_gloss2exponent.value;
9212                 }
9213         }
9214         t->specularscale *= t->specularscalemod;
9215         t->specularpower *= t->specularpowermod;
9216
9217         // lightmaps mode looks bad with dlights using actual texturing, so turn
9218         // off the colormap and glossmap, but leave the normalmap on as it still
9219         // accurately represents the shading involved
9220         if (gl_lightmaps.integer)
9221         {
9222                 t->basetexture = r_texture_grey128;
9223                 t->pantstexture = r_texture_black;
9224                 t->shirttexture = r_texture_black;
9225                 t->nmaptexture = r_texture_blanknormalmap;
9226                 t->glosstexture = r_texture_black;
9227                 t->glowtexture = NULL;
9228                 t->fogtexture = NULL;
9229                 t->reflectmasktexture = NULL;
9230                 t->backgroundbasetexture = NULL;
9231                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9232                 t->backgroundglosstexture = r_texture_black;
9233                 t->backgroundglowtexture = NULL;
9234                 t->specularscale = 0;
9235                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9236         }
9237
9238         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9239         VectorClear(t->dlightcolor);
9240         t->currentnumlayers = 0;
9241         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9242         {
9243                 int blendfunc1, blendfunc2;
9244                 qboolean depthmask;
9245                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9246                 {
9247                         blendfunc1 = GL_SRC_ALPHA;
9248                         blendfunc2 = GL_ONE;
9249                 }
9250                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9251                 {
9252                         blendfunc1 = GL_SRC_ALPHA;
9253                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9254                 }
9255                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9256                 {
9257                         blendfunc1 = t->customblendfunc[0];
9258                         blendfunc2 = t->customblendfunc[1];
9259                 }
9260                 else
9261                 {
9262                         blendfunc1 = GL_ONE;
9263                         blendfunc2 = GL_ZERO;
9264                 }
9265                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9266                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9267                 {
9268                         // fullbright is not affected by r_refdef.lightmapintensity
9269                         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]);
9270                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9271                                 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]);
9272                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9273                                 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]);
9274                 }
9275                 else
9276                 {
9277                         vec3_t ambientcolor;
9278                         float colorscale;
9279                         // set the color tint used for lights affecting this surface
9280                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9281                         colorscale = 2;
9282                         // q3bsp has no lightmap updates, so the lightstylevalue that
9283                         // would normally be baked into the lightmap must be
9284                         // applied to the color
9285                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9286                         if (model->type == mod_brushq3)
9287                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9288                         colorscale *= r_refdef.lightmapintensity;
9289                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9290                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9291                         // basic lit geometry
9292                         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]);
9293                         // add pants/shirt if needed
9294                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9295                                 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]);
9296                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9297                                 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]);
9298                         // now add ambient passes if needed
9299                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9300                         {
9301                                 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]);
9302                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9303                                         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]);
9304                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9305                                         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]);
9306                         }
9307                 }
9308                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9309                         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]);
9310                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9311                 {
9312                         // if this is opaque use alpha blend which will darken the earlier
9313                         // passes cheaply.
9314                         //
9315                         // if this is an alpha blended material, all the earlier passes
9316                         // were darkened by fog already, so we only need to add the fog
9317                         // color ontop through the fog mask texture
9318                         //
9319                         // if this is an additive blended material, all the earlier passes
9320                         // were darkened by fog already, and we should not add fog color
9321                         // (because the background was not darkened, there is no fog color
9322                         // that was lost behind it).
9323                         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]);
9324                 }
9325         }
9326
9327         return t->currentframe;
9328 }
9329
9330 rsurfacestate_t rsurface;
9331
9332 void R_Mesh_ResizeArrays(int newvertices)
9333 {
9334         float *base;
9335         if (rsurface.array_size >= newvertices)
9336                 return;
9337         if (rsurface.array_modelvertex3f)
9338                 Mem_Free(rsurface.array_modelvertex3f);
9339         rsurface.array_size = (newvertices + 1023) & ~1023;
9340         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9341         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9342         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9343         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9344         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9345         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9346         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9347         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9348         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9349         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9350         rsurface.array_color4f           = base + rsurface.array_size * 27;
9351         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9352 }
9353
9354 void RSurf_ActiveWorldEntity(void)
9355 {
9356         dp_model_t *model = r_refdef.scene.worldmodel;
9357         //if (rsurface.entity == r_refdef.scene.worldentity)
9358         //      return;
9359         rsurface.entity = r_refdef.scene.worldentity;
9360         rsurface.skeleton = NULL;
9361         rsurface.ent_skinnum = 0;
9362         rsurface.ent_qwskin = -1;
9363         rsurface.ent_shadertime = 0;
9364         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9365         if (rsurface.array_size < model->surfmesh.num_vertices)
9366                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9367         rsurface.matrix = identitymatrix;
9368         rsurface.inversematrix = identitymatrix;
9369         rsurface.matrixscale = 1;
9370         rsurface.inversematrixscale = 1;
9371         R_EntityMatrix(&identitymatrix);
9372         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9373         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9374         rsurface.fograngerecip = r_refdef.fograngerecip;
9375         rsurface.fogheightfade = r_refdef.fogheightfade;
9376         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9377         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9378         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9379         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9380         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9381         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9382         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9383         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9384         rsurface.colormod[3] = 1;
9385         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);
9386         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9387         rsurface.frameblend[0].lerp = 1;
9388         rsurface.ent_alttextures = false;
9389         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9390         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9391         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9392         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9393         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9394         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9395         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9396         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9397         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9398         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9399         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9400         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9401         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9402         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9403         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9404         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9405         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9406         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9407         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9408         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9409         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9410         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9411         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9412         rsurface.modelelement3i = model->surfmesh.data_element3i;
9413         rsurface.modelelement3s = model->surfmesh.data_element3s;
9414         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9415         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9416         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9417         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9418         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9419         rsurface.modelsurfaces = model->data_surfaces;
9420         rsurface.generatedvertex = false;
9421         rsurface.vertex3f  = rsurface.modelvertex3f;
9422         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9423         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9424         rsurface.svector3f = rsurface.modelsvector3f;
9425         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9426         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9427         rsurface.tvector3f = rsurface.modeltvector3f;
9428         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9429         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9430         rsurface.normal3f  = rsurface.modelnormal3f;
9431         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9432         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9433         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9434 }
9435
9436 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9437 {
9438         dp_model_t *model = ent->model;
9439         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9440         //      return;
9441         rsurface.entity = (entity_render_t *)ent;
9442         rsurface.skeleton = ent->skeleton;
9443         rsurface.ent_skinnum = ent->skinnum;
9444         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;
9445         rsurface.ent_shadertime = ent->shadertime;
9446         rsurface.ent_flags = ent->flags;
9447         if (rsurface.array_size < model->surfmesh.num_vertices)
9448                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9449         rsurface.matrix = ent->matrix;
9450         rsurface.inversematrix = ent->inversematrix;
9451         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9452         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9453         R_EntityMatrix(&rsurface.matrix);
9454         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9455         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9456         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9457         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9458         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9459         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9460         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9461         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9462         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9463         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9464         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9465         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9466         rsurface.colormod[3] = ent->alpha;
9467         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9468         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9469         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9470         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9471         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9472         if (ent->model->brush.submodel && !prepass)
9473         {
9474                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9475                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9476         }
9477         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9478         {
9479                 if (ent->animcache_vertex3f && !r_framedata_failed)
9480                 {
9481                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9482                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9483                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9484                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9485                 }
9486                 else if (wanttangents)
9487                 {
9488                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9489                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9490                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9491                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9492                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9493                 }
9494                 else if (wantnormals)
9495                 {
9496                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9497                         rsurface.modelsvector3f = NULL;
9498                         rsurface.modeltvector3f = NULL;
9499                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9500                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9501                 }
9502                 else
9503                 {
9504                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9505                         rsurface.modelsvector3f = NULL;
9506                         rsurface.modeltvector3f = NULL;
9507                         rsurface.modelnormal3f = NULL;
9508                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9509                 }
9510                 rsurface.modelvertex3f_bufferobject = 0;
9511                 rsurface.modelvertex3f_bufferoffset = 0;
9512                 rsurface.modelsvector3f_bufferobject = 0;
9513                 rsurface.modelsvector3f_bufferoffset = 0;
9514                 rsurface.modeltvector3f_bufferobject = 0;
9515                 rsurface.modeltvector3f_bufferoffset = 0;
9516                 rsurface.modelnormal3f_bufferobject = 0;
9517                 rsurface.modelnormal3f_bufferoffset = 0;
9518                 rsurface.generatedvertex = true;
9519         }
9520         else
9521         {
9522                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9523                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9524                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9525                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9526                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9527                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9528                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9529                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9530                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9531                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9532                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9533                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9534                 rsurface.generatedvertex = false;
9535         }
9536         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9537         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9538         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9539         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9540         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9541         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9542         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9543         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9544         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9545         rsurface.modelelement3i = model->surfmesh.data_element3i;
9546         rsurface.modelelement3s = model->surfmesh.data_element3s;
9547         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9548         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9549         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9550         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9551         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9552         rsurface.modelsurfaces = model->data_surfaces;
9553         rsurface.vertex3f  = rsurface.modelvertex3f;
9554         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9555         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9556         rsurface.svector3f = rsurface.modelsvector3f;
9557         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9558         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9559         rsurface.tvector3f = rsurface.modeltvector3f;
9560         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9561         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9562         rsurface.normal3f  = rsurface.modelnormal3f;
9563         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9564         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9565         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9566 }
9567
9568 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)
9569 {
9570         rsurface.entity = r_refdef.scene.worldentity;
9571         rsurface.skeleton = NULL;
9572         rsurface.ent_skinnum = 0;
9573         rsurface.ent_qwskin = -1;
9574         rsurface.ent_shadertime = shadertime;
9575         rsurface.ent_flags = entflags;
9576         rsurface.modelnum_vertices = numvertices;
9577         rsurface.modelnum_triangles = numtriangles;
9578         if (rsurface.array_size < rsurface.modelnum_vertices)
9579                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9580         rsurface.matrix = *matrix;
9581         rsurface.inversematrix = *inversematrix;
9582         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9583         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9584         R_EntityMatrix(&rsurface.matrix);
9585         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9586         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9587         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9588         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9589         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9590         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9591         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9592         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9593         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9594         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9595         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9596         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9597         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);
9598         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9599         rsurface.frameblend[0].lerp = 1;
9600         rsurface.ent_alttextures = false;
9601         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9602         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9603         if (wanttangents)
9604         {
9605                 rsurface.modelvertex3f = vertex3f;
9606                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9607                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9608                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9609         }
9610         else if (wantnormals)
9611         {
9612                 rsurface.modelvertex3f = vertex3f;
9613                 rsurface.modelsvector3f = NULL;
9614                 rsurface.modeltvector3f = NULL;
9615                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9616         }
9617         else
9618         {
9619                 rsurface.modelvertex3f = vertex3f;
9620                 rsurface.modelsvector3f = NULL;
9621                 rsurface.modeltvector3f = NULL;
9622                 rsurface.modelnormal3f = NULL;
9623         }
9624         rsurface.modelvertex3f_bufferobject = 0;
9625         rsurface.modelvertex3f_bufferoffset = 0;
9626         rsurface.modelsvector3f_bufferobject = 0;
9627         rsurface.modelsvector3f_bufferoffset = 0;
9628         rsurface.modeltvector3f_bufferobject = 0;
9629         rsurface.modeltvector3f_bufferoffset = 0;
9630         rsurface.modelnormal3f_bufferobject = 0;
9631         rsurface.modelnormal3f_bufferoffset = 0;
9632         rsurface.generatedvertex = true;
9633         rsurface.modellightmapcolor4f  = color4f;
9634         rsurface.modellightmapcolor4f_bufferobject = 0;
9635         rsurface.modellightmapcolor4f_bufferoffset = 0;
9636         rsurface.modeltexcoordtexture2f  = texcoord2f;
9637         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9638         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9639         rsurface.modeltexcoordlightmap2f  = NULL;
9640         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9641         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9642         rsurface.modelelement3i = element3i;
9643         rsurface.modelelement3s = element3s;
9644         rsurface.modelelement3i_bufferobject = 0;
9645         rsurface.modelelement3s_bufferobject = 0;
9646         rsurface.modellightmapoffsets = NULL;
9647         rsurface.modelsurfaces = NULL;
9648         rsurface.vertex3f  = rsurface.modelvertex3f;
9649         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9650         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9651         rsurface.svector3f = rsurface.modelsvector3f;
9652         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9653         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9654         rsurface.tvector3f = rsurface.modeltvector3f;
9655         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9656         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9657         rsurface.normal3f  = rsurface.modelnormal3f;
9658         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9659         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9660         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9661
9662         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9663         {
9664                 if ((wantnormals || wanttangents) && !normal3f)
9665                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9666                 if (wanttangents && !svector3f)
9667                         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);
9668         }
9669 }
9670
9671 float RSurf_FogPoint(const float *v)
9672 {
9673         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9674         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9675         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9676         float FogHeightFade = r_refdef.fogheightfade;
9677         float fogfrac;
9678         unsigned int fogmasktableindex;
9679         if (r_refdef.fogplaneviewabove)
9680                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9681         else
9682                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9683         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9684         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9685 }
9686
9687 float RSurf_FogVertex(const float *v)
9688 {
9689         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9690         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9691         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9692         float FogHeightFade = rsurface.fogheightfade;
9693         float fogfrac;
9694         unsigned int fogmasktableindex;
9695         if (r_refdef.fogplaneviewabove)
9696                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9697         else
9698                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9699         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9700         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9701 }
9702
9703 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9704 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9705 {
9706         int deformindex;
9707         int texturesurfaceindex;
9708         int i, j;
9709         float amplitude;
9710         float animpos;
9711         float scale;
9712         const float *v1, *in_tc;
9713         float *out_tc;
9714         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9715         float waveparms[4];
9716         q3shaderinfo_deform_t *deform;
9717         // 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
9718         if (rsurface.generatedvertex)
9719         {
9720                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9721                         generatenormals = true;
9722                 for (i = 0;i < Q3MAXDEFORMS;i++)
9723                 {
9724                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9725                         {
9726                                 generatetangents = true;
9727                                 generatenormals = true;
9728                         }
9729                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9730                                 generatenormals = true;
9731                 }
9732                 if (generatenormals && !rsurface.modelnormal3f)
9733                 {
9734                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9735                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9736                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9737                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9738                 }
9739                 if (generatetangents && !rsurface.modelsvector3f)
9740                 {
9741                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9742                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9743                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9744                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9745                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9746                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9747                         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);
9748                 }
9749         }
9750         rsurface.vertex3f  = rsurface.modelvertex3f;
9751         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9752         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9753         rsurface.svector3f = rsurface.modelsvector3f;
9754         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9755         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9756         rsurface.tvector3f = rsurface.modeltvector3f;
9757         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9758         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9759         rsurface.normal3f  = rsurface.modelnormal3f;
9760         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9761         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9762         // if vertices are deformed (sprite flares and things in maps, possibly
9763         // water waves, bulges and other deformations), generate them into
9764         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9765         // (may be static model data or generated data for an animated model, or
9766         //  the previous deform pass)
9767         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9768         {
9769                 switch (deform->deform)
9770                 {
9771                 default:
9772                 case Q3DEFORM_PROJECTIONSHADOW:
9773                 case Q3DEFORM_TEXT0:
9774                 case Q3DEFORM_TEXT1:
9775                 case Q3DEFORM_TEXT2:
9776                 case Q3DEFORM_TEXT3:
9777                 case Q3DEFORM_TEXT4:
9778                 case Q3DEFORM_TEXT5:
9779                 case Q3DEFORM_TEXT6:
9780                 case Q3DEFORM_TEXT7:
9781                 case Q3DEFORM_NONE:
9782                         break;
9783                 case Q3DEFORM_AUTOSPRITE:
9784                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9785                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9786                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9787                         VectorNormalize(newforward);
9788                         VectorNormalize(newright);
9789                         VectorNormalize(newup);
9790                         // make deformed versions of only the model vertices used by the specified surfaces
9791                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9792                         {
9793                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9794                                 // a single autosprite surface can contain multiple sprites...
9795                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9796                                 {
9797                                         VectorClear(center);
9798                                         for (i = 0;i < 4;i++)
9799                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9800                                         VectorScale(center, 0.25f, center);
9801                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9802                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9803                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9804                                         for (i = 0;i < 4;i++)
9805                                         {
9806                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9807                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9808                                         }
9809                                 }
9810                                 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);
9811                                 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);
9812                         }
9813                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9814                         rsurface.vertex3f_bufferobject = 0;
9815                         rsurface.vertex3f_bufferoffset = 0;
9816                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9817                         rsurface.svector3f_bufferobject = 0;
9818                         rsurface.svector3f_bufferoffset = 0;
9819                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9820                         rsurface.tvector3f_bufferobject = 0;
9821                         rsurface.tvector3f_bufferoffset = 0;
9822                         rsurface.normal3f = rsurface.array_deformednormal3f;
9823                         rsurface.normal3f_bufferobject = 0;
9824                         rsurface.normal3f_bufferoffset = 0;
9825                         break;
9826                 case Q3DEFORM_AUTOSPRITE2:
9827                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9828                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9829                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9830                         VectorNormalize(newforward);
9831                         VectorNormalize(newright);
9832                         VectorNormalize(newup);
9833                         // make deformed versions of only the model vertices used by the specified surfaces
9834                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9835                         {
9836                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9837                                 const float *v1, *v2;
9838                                 vec3_t start, end;
9839                                 float f, l;
9840                                 struct
9841                                 {
9842                                         float length2;
9843                                         const float *v1;
9844                                         const float *v2;
9845                                 }
9846                                 shortest[2];
9847                                 memset(shortest, 0, sizeof(shortest));
9848                                 // a single autosprite surface can contain multiple sprites...
9849                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9850                                 {
9851                                         VectorClear(center);
9852                                         for (i = 0;i < 4;i++)
9853                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9854                                         VectorScale(center, 0.25f, center);
9855                                         // find the two shortest edges, then use them to define the
9856                                         // axis vectors for rotating around the central axis
9857                                         for (i = 0;i < 6;i++)
9858                                         {
9859                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9860                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9861 #if 0
9862                                                 Debug_PolygonBegin(NULL, 0);
9863                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9864                                                 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);
9865                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9866                                                 Debug_PolygonEnd();
9867 #endif
9868                                                 l = VectorDistance2(v1, v2);
9869                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9870                                                 if (v1[2] != v2[2])
9871                                                         l += (1.0f / 1024.0f);
9872                                                 if (shortest[0].length2 > l || i == 0)
9873                                                 {
9874                                                         shortest[1] = shortest[0];
9875                                                         shortest[0].length2 = l;
9876                                                         shortest[0].v1 = v1;
9877                                                         shortest[0].v2 = v2;
9878                                                 }
9879                                                 else if (shortest[1].length2 > l || i == 1)
9880                                                 {
9881                                                         shortest[1].length2 = l;
9882                                                         shortest[1].v1 = v1;
9883                                                         shortest[1].v2 = v2;
9884                                                 }
9885                                         }
9886                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9887                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9888 #if 0
9889                                         Debug_PolygonBegin(NULL, 0);
9890                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9891                                         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);
9892                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9893                                         Debug_PolygonEnd();
9894 #endif
9895                                         // this calculates the right vector from the shortest edge
9896                                         // and the up vector from the edge midpoints
9897                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9898                                         VectorNormalize(right);
9899                                         VectorSubtract(end, start, up);
9900                                         VectorNormalize(up);
9901                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9902                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9903                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9904                                         VectorNegate(forward, forward);
9905                                         VectorReflect(forward, 0, up, forward);
9906                                         VectorNormalize(forward);
9907                                         CrossProduct(up, forward, newright);
9908                                         VectorNormalize(newright);
9909 #if 0
9910                                         Debug_PolygonBegin(NULL, 0);
9911                                         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);
9912                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9913                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9914                                         Debug_PolygonEnd();
9915 #endif
9916 #if 0
9917                                         Debug_PolygonBegin(NULL, 0);
9918                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9919                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9920                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9921                                         Debug_PolygonEnd();
9922 #endif
9923                                         // rotate the quad around the up axis vector, this is made
9924                                         // especially easy by the fact we know the quad is flat,
9925                                         // so we only have to subtract the center position and
9926                                         // measure distance along the right vector, and then
9927                                         // multiply that by the newright vector and add back the
9928                                         // center position
9929                                         // we also need to subtract the old position to undo the
9930                                         // displacement from the center, which we do with a
9931                                         // DotProduct, the subtraction/addition of center is also
9932                                         // optimized into DotProducts here
9933                                         l = DotProduct(right, center);
9934                                         for (i = 0;i < 4;i++)
9935                                         {
9936                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9937                                                 f = DotProduct(right, v1) - l;
9938                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9939                                         }
9940                                 }
9941                                 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);
9942                                 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);
9943                         }
9944                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9945                         rsurface.vertex3f_bufferobject = 0;
9946                         rsurface.vertex3f_bufferoffset = 0;
9947                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9948                         rsurface.svector3f_bufferobject = 0;
9949                         rsurface.svector3f_bufferoffset = 0;
9950                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9951                         rsurface.tvector3f_bufferobject = 0;
9952                         rsurface.tvector3f_bufferoffset = 0;
9953                         rsurface.normal3f = rsurface.array_deformednormal3f;
9954                         rsurface.normal3f_bufferobject = 0;
9955                         rsurface.normal3f_bufferoffset = 0;
9956                         break;
9957                 case Q3DEFORM_NORMAL:
9958                         // deform the normals to make reflections wavey
9959                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9960                         {
9961                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9962                                 for (j = 0;j < surface->num_vertices;j++)
9963                                 {
9964                                         float vertex[3];
9965                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9966                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9967                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9968                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9969                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9970                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9971                                         VectorNormalize(normal);
9972                                 }
9973                                 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);
9974                         }
9975                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9976                         rsurface.svector3f_bufferobject = 0;
9977                         rsurface.svector3f_bufferoffset = 0;
9978                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9979                         rsurface.tvector3f_bufferobject = 0;
9980                         rsurface.tvector3f_bufferoffset = 0;
9981                         rsurface.normal3f = rsurface.array_deformednormal3f;
9982                         rsurface.normal3f_bufferobject = 0;
9983                         rsurface.normal3f_bufferoffset = 0;
9984                         break;
9985                 case Q3DEFORM_WAVE:
9986                         // deform vertex array to make wavey water and flags and such
9987                         waveparms[0] = deform->waveparms[0];
9988                         waveparms[1] = deform->waveparms[1];
9989                         waveparms[2] = deform->waveparms[2];
9990                         waveparms[3] = deform->waveparms[3];
9991                         // this is how a divisor of vertex influence on deformation
9992                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9993                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9994                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9995                         {
9996                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9997                                 for (j = 0;j < surface->num_vertices;j++)
9998                                 {
9999                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
10000                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10001                                         // if the wavefunc depends on time, evaluate it per-vertex
10002                                         if (waveparms[3])
10003                                         {
10004                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
10005                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10006                                         }
10007                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
10008                                 }
10009                         }
10010                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10011                         rsurface.vertex3f_bufferobject = 0;
10012                         rsurface.vertex3f_bufferoffset = 0;
10013                         break;
10014                 case Q3DEFORM_BULGE:
10015                         // deform vertex array to make the surface have moving bulges
10016                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10017                         {
10018                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10019                                 for (j = 0;j < surface->num_vertices;j++)
10020                                 {
10021                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
10022                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10023                                 }
10024                         }
10025                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10026                         rsurface.vertex3f_bufferobject = 0;
10027                         rsurface.vertex3f_bufferoffset = 0;
10028                         break;
10029                 case Q3DEFORM_MOVE:
10030                         // deform vertex array
10031                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10032                         VectorScale(deform->parms, scale, waveparms);
10033                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10034                         {
10035                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10036                                 for (j = 0;j < surface->num_vertices;j++)
10037                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
10038                         }
10039                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
10040                         rsurface.vertex3f_bufferobject = 0;
10041                         rsurface.vertex3f_bufferoffset = 0;
10042                         break;
10043                 }
10044         }
10045         // generate texcoords based on the chosen texcoord source
10046         switch(rsurface.texture->tcgen.tcgen)
10047         {
10048         default:
10049         case Q3TCGEN_TEXTURE:
10050                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
10051                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
10052                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10053                 break;
10054         case Q3TCGEN_LIGHTMAP:
10055                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
10056                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
10057                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
10058                 break;
10059         case Q3TCGEN_VECTOR:
10060                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10061                 {
10062                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10063                         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)
10064                         {
10065                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10066                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10067                         }
10068                 }
10069                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10070                 rsurface.texcoordtexture2f_bufferobject  = 0;
10071                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10072                 break;
10073         case Q3TCGEN_ENVIRONMENT:
10074                 // make environment reflections using a spheremap
10075                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10076                 {
10077                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10078                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10079                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10080                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10081                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10082                         {
10083                                 // identical to Q3A's method, but executed in worldspace so
10084                                 // carried models can be shiny too
10085
10086                                 float viewer[3], d, reflected[3], worldreflected[3];
10087
10088                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10089                                 // VectorNormalize(viewer);
10090
10091                                 d = DotProduct(normal, viewer);
10092
10093                                 reflected[0] = normal[0]*2*d - viewer[0];
10094                                 reflected[1] = normal[1]*2*d - viewer[1];
10095                                 reflected[2] = normal[2]*2*d - viewer[2];
10096                                 // note: this is proportinal to viewer, so we can normalize later
10097
10098                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10099                                 VectorNormalize(worldreflected);
10100
10101                                 // note: this sphere map only uses world x and z!
10102                                 // so positive and negative y will LOOK THE SAME.
10103                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10104                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10105                         }
10106                 }
10107                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10108                 rsurface.texcoordtexture2f_bufferobject  = 0;
10109                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10110                 break;
10111         }
10112         // the only tcmod that needs software vertex processing is turbulent, so
10113         // check for it here and apply the changes if needed
10114         // and we only support that as the first one
10115         // (handling a mixture of turbulent and other tcmods would be problematic
10116         //  without punting it entirely to a software path)
10117         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10118         {
10119                 amplitude = rsurface.texture->tcmods[0].parms[1];
10120                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10121                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10122                 {
10123                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10124                         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)
10125                         {
10126                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10127                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10128                         }
10129                 }
10130                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10131                 rsurface.texcoordtexture2f_bufferobject  = 0;
10132                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10133         }
10134         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10135         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10136         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10137         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10138 }
10139
10140 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10141 {
10142         int i, j;
10143         const msurface_t *surface = texturesurfacelist[0];
10144         const msurface_t *surface2;
10145         int firstvertex;
10146         int endvertex;
10147         int numvertices;
10148         int numtriangles;
10149         // TODO: lock all array ranges before render, rather than on each surface
10150         if (texturenumsurfaces == 1)
10151                 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);
10152         else if (r_batchmode.integer == 2)
10153         {
10154                 #define MAXBATCHTRIANGLES 4096
10155                 int batchtriangles = 0;
10156                 static int batchelements[MAXBATCHTRIANGLES*3];
10157                 for (i = 0;i < texturenumsurfaces;i = j)
10158                 {
10159                         surface = texturesurfacelist[i];
10160                         j = i + 1;
10161                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10162                         {
10163                                 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);
10164                                 continue;
10165                         }
10166                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10167                         batchtriangles = surface->num_triangles;
10168                         firstvertex = surface->num_firstvertex;
10169                         endvertex = surface->num_firstvertex + surface->num_vertices;
10170                         for (;j < texturenumsurfaces;j++)
10171                         {
10172                                 surface2 = texturesurfacelist[j];
10173                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10174                                         break;
10175                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10176                                 batchtriangles += surface2->num_triangles;
10177                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10178                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10179                         }
10180                         surface2 = texturesurfacelist[j-1];
10181                         numvertices = endvertex - firstvertex;
10182                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10183                 }
10184         }
10185         else if (r_batchmode.integer == 1)
10186         {
10187                 for (i = 0;i < texturenumsurfaces;i = j)
10188                 {
10189                         surface = texturesurfacelist[i];
10190                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10191                                 if (texturesurfacelist[j] != surface2)
10192                                         break;
10193                         surface2 = texturesurfacelist[j-1];
10194                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10195                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10196                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10197                 }
10198         }
10199         else
10200         {
10201                 for (i = 0;i < texturenumsurfaces;i++)
10202                 {
10203                         surface = texturesurfacelist[i];
10204                         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);
10205                 }
10206         }
10207 }
10208
10209 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10210 {
10211         switch(vid.renderpath)
10212         {
10213         case RENDERPATH_CGGL:
10214 #ifdef SUPPORTCG
10215                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10216                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10217 #endif
10218                 break;
10219         case RENDERPATH_GL20:
10220                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10221                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10222                 break;
10223         case RENDERPATH_GL13:
10224         case RENDERPATH_GL11:
10225                 R_Mesh_TexBind(0, surface->lightmaptexture);
10226                 break;
10227         }
10228 }
10229
10230 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10231 {
10232         // pick the closest matching water plane and bind textures
10233         int planeindex, vertexindex;
10234         float d, bestd;
10235         vec3_t vert;
10236         const float *v;
10237         r_waterstate_waterplane_t *p, *bestp;
10238         bestd = 0;
10239         bestp = NULL;
10240         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10241         {
10242                 d = 0;
10243                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10244                 {
10245                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10246                         d += fabs(PlaneDiff(vert, &p->plane));
10247                 }
10248                 if (bestd > d || !bestp)
10249                 {
10250                         bestd = d;
10251                         bestp = p;
10252                 }
10253         }
10254         switch(vid.renderpath)
10255         {
10256         case RENDERPATH_CGGL:
10257 #ifdef SUPPORTCG
10258                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10259                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10260 #endif
10261                 break;
10262         case RENDERPATH_GL20:
10263                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10264                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10265                 break;
10266         case RENDERPATH_GL13:
10267         case RENDERPATH_GL11:
10268                 break;
10269         }
10270 }
10271
10272 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10273 {
10274         int i;
10275         const msurface_t *surface;
10276         if (r_waterstate.renderingscene)
10277                 return;
10278         for (i = 0;i < texturenumsurfaces;i++)
10279         {
10280                 surface = texturesurfacelist[i];
10281                 RSurf_BindLightmapForSurface(surface);
10282                 RSurf_BindReflectionForSurface(surface);
10283                 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);
10284         }
10285 }
10286
10287 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10288 {
10289         int i;
10290         int j;
10291         const msurface_t *surface = texturesurfacelist[0];
10292         const msurface_t *surface2;
10293         int firstvertex;
10294         int endvertex;
10295         int numvertices;
10296         int numtriangles;
10297         if (texturenumsurfaces == 1)
10298         {
10299                 RSurf_BindLightmapForSurface(surface);
10300                 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);
10301         }
10302         else if (r_batchmode.integer == 2)
10303         {
10304 #define MAXBATCHTRIANGLES 4096
10305                 int batchtriangles = 0;
10306                 static int batchelements[MAXBATCHTRIANGLES*3];
10307                 for (i = 0;i < texturenumsurfaces;i = j)
10308                 {
10309                         surface = texturesurfacelist[i];
10310                         RSurf_BindLightmapForSurface(surface);
10311                         j = i + 1;
10312                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10313                         {
10314                                 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);
10315                                 continue;
10316                         }
10317                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10318                         batchtriangles = surface->num_triangles;
10319                         firstvertex = surface->num_firstvertex;
10320                         endvertex = surface->num_firstvertex + surface->num_vertices;
10321                         for (;j < texturenumsurfaces;j++)
10322                         {
10323                                 surface2 = texturesurfacelist[j];
10324                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10325                                         break;
10326                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10327                                 batchtriangles += surface2->num_triangles;
10328                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10329                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10330                         }
10331                         surface2 = texturesurfacelist[j-1];
10332                         numvertices = endvertex - firstvertex;
10333                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10334                 }
10335         }
10336         else if (r_batchmode.integer == 1)
10337         {
10338 #if 0
10339                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10340                 for (i = 0;i < texturenumsurfaces;i = j)
10341                 {
10342                         surface = texturesurfacelist[i];
10343                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10344                                 if (texturesurfacelist[j] != surface2)
10345                                         break;
10346                         Con_Printf(" %i", j - i);
10347                 }
10348                 Con_Printf("\n");
10349                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10350 #endif
10351                 for (i = 0;i < texturenumsurfaces;i = j)
10352                 {
10353                         surface = texturesurfacelist[i];
10354                         RSurf_BindLightmapForSurface(surface);
10355                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10356                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10357                                         break;
10358 #if 0
10359                         Con_Printf(" %i", j - i);
10360 #endif
10361                         surface2 = texturesurfacelist[j-1];
10362                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10363                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10364                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10365                 }
10366 #if 0
10367                 Con_Printf("\n");
10368 #endif
10369         }
10370         else
10371         {
10372                 for (i = 0;i < texturenumsurfaces;i++)
10373                 {
10374                         surface = texturesurfacelist[i];
10375                         RSurf_BindLightmapForSurface(surface);
10376                         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);
10377                 }
10378         }
10379 }
10380
10381 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10382 {
10383         int j;
10384         int texturesurfaceindex;
10385         if (r_showsurfaces.integer == 2)
10386         {
10387                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10388                 {
10389                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10390                         for (j = 0;j < surface->num_triangles;j++)
10391                         {
10392                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10393                                 GL_Color(f, f, f, 1);
10394                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10395                         }
10396                 }
10397         }
10398         else
10399         {
10400                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10401                 {
10402                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10403                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10404                         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);
10405                         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);
10406                 }
10407         }
10408 }
10409
10410 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10411 {
10412         int texturesurfaceindex;
10413         int i;
10414         const float *v;
10415         float *c2;
10416         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10417         {
10418                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10419                 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)
10420                 {
10421                         c2[0] = 0.5;
10422                         c2[1] = 0.5;
10423                         c2[2] = 0.5;
10424                         c2[3] = 1;
10425                 }
10426         }
10427         rsurface.lightmapcolor4f = rsurface.array_color4f;
10428         rsurface.lightmapcolor4f_bufferobject = 0;
10429         rsurface.lightmapcolor4f_bufferoffset = 0;
10430 }
10431
10432 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10433 {
10434         int texturesurfaceindex;
10435         int i;
10436         float f;
10437         const float *v;
10438         const float *c;
10439         float *c2;
10440         if (rsurface.lightmapcolor4f)
10441         {
10442                 // generate color arrays for the surfaces in this list
10443                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10444                 {
10445                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10446                         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)
10447                         {
10448                                 f = RSurf_FogVertex(v);
10449                                 c2[0] = c[0] * f;
10450                                 c2[1] = c[1] * f;
10451                                 c2[2] = c[2] * f;
10452                                 c2[3] = c[3];
10453                         }
10454                 }
10455         }
10456         else
10457         {
10458                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10459                 {
10460                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10461                         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)
10462                         {
10463                                 f = RSurf_FogVertex(v);
10464                                 c2[0] = f;
10465                                 c2[1] = f;
10466                                 c2[2] = f;
10467                                 c2[3] = 1;
10468                         }
10469                 }
10470         }
10471         rsurface.lightmapcolor4f = rsurface.array_color4f;
10472         rsurface.lightmapcolor4f_bufferobject = 0;
10473         rsurface.lightmapcolor4f_bufferoffset = 0;
10474 }
10475
10476 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10477 {
10478         int texturesurfaceindex;
10479         int i;
10480         float f;
10481         const float *v;
10482         const float *c;
10483         float *c2;
10484         if (!rsurface.lightmapcolor4f)
10485                 return;
10486         // generate color arrays for the surfaces in this list
10487         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10488         {
10489                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10490                 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)
10491                 {
10492                         f = RSurf_FogVertex(v);
10493                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10494                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10495                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10496                         c2[3] = c[3];
10497                 }
10498         }
10499         rsurface.lightmapcolor4f = rsurface.array_color4f;
10500         rsurface.lightmapcolor4f_bufferobject = 0;
10501         rsurface.lightmapcolor4f_bufferoffset = 0;
10502 }
10503
10504 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10505 {
10506         int texturesurfaceindex;
10507         int i;
10508         const float *c;
10509         float *c2;
10510         if (!rsurface.lightmapcolor4f)
10511                 return;
10512         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10513         {
10514                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10515                 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)
10516                 {
10517                         c2[0] = c[0] * r;
10518                         c2[1] = c[1] * g;
10519                         c2[2] = c[2] * b;
10520                         c2[3] = c[3] * a;
10521                 }
10522         }
10523         rsurface.lightmapcolor4f = rsurface.array_color4f;
10524         rsurface.lightmapcolor4f_bufferobject = 0;
10525         rsurface.lightmapcolor4f_bufferoffset = 0;
10526 }
10527
10528 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10529 {
10530         int texturesurfaceindex;
10531         int i;
10532         const float *c;
10533         float *c2;
10534         if (!rsurface.lightmapcolor4f)
10535                 return;
10536         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10537         {
10538                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10539                 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)
10540                 {
10541                         c2[0] = c[0] + r_refdef.scene.ambient;
10542                         c2[1] = c[1] + r_refdef.scene.ambient;
10543                         c2[2] = c[2] + r_refdef.scene.ambient;
10544                         c2[3] = c[3];
10545                 }
10546         }
10547         rsurface.lightmapcolor4f = rsurface.array_color4f;
10548         rsurface.lightmapcolor4f_bufferobject = 0;
10549         rsurface.lightmapcolor4f_bufferoffset = 0;
10550 }
10551
10552 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10553 {
10554         // TODO: optimize
10555         rsurface.lightmapcolor4f = NULL;
10556         rsurface.lightmapcolor4f_bufferobject = 0;
10557         rsurface.lightmapcolor4f_bufferoffset = 0;
10558         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10559         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10560         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10561         GL_Color(r, g, b, a);
10562         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10563 }
10564
10565 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10566 {
10567         // TODO: optimize applyfog && applycolor case
10568         // just apply fog if necessary, and tint the fog color array if necessary
10569         rsurface.lightmapcolor4f = NULL;
10570         rsurface.lightmapcolor4f_bufferobject = 0;
10571         rsurface.lightmapcolor4f_bufferoffset = 0;
10572         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10573         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10574         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10575         GL_Color(r, g, b, a);
10576         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10577 }
10578
10579 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10580 {
10581         int texturesurfaceindex;
10582         int i;
10583         float *c;
10584         // TODO: optimize
10585         if (texturesurfacelist[0]->lightmapinfo)
10586         {
10587                 // generate color arrays for the surfaces in this list
10588                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10589                 {
10590                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10591                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10592                         {
10593                                 if (surface->lightmapinfo->samples)
10594                                 {
10595                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10596                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10597                                         VectorScale(lm, scale, c);
10598                                         if (surface->lightmapinfo->styles[1] != 255)
10599                                         {
10600                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10601                                                 lm += size3;
10602                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10603                                                 VectorMA(c, scale, lm, c);
10604                                                 if (surface->lightmapinfo->styles[2] != 255)
10605                                                 {
10606                                                         lm += size3;
10607                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10608                                                         VectorMA(c, scale, lm, c);
10609                                                         if (surface->lightmapinfo->styles[3] != 255)
10610                                                         {
10611                                                                 lm += size3;
10612                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10613                                                                 VectorMA(c, scale, lm, c);
10614                                                         }
10615                                                 }
10616                                         }
10617                                 }
10618                                 else
10619                                         VectorClear(c);
10620                                 c[3] = 1;
10621                         }
10622                 }
10623                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10624                 rsurface.lightmapcolor4f_bufferobject = 0;
10625                 rsurface.lightmapcolor4f_bufferoffset = 0;
10626         }
10627         else
10628         {
10629                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10630                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10631                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10632         }
10633         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10634         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10635         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10636         GL_Color(r, g, b, a);
10637         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10638 }
10639
10640 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10641 {
10642         int texturesurfaceindex;
10643         int i;
10644         float f;
10645         float alpha;
10646         const float *v;
10647         const float *n;
10648         float *c;
10649         vec3_t ambientcolor;
10650         vec3_t diffusecolor;
10651         vec3_t lightdir;
10652         // TODO: optimize
10653         // model lighting
10654         VectorCopy(rsurface.modellight_lightdir, lightdir);
10655         f = 0.5f * r_refdef.lightmapintensity;
10656         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10657         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10658         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10659         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10660         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10661         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10662         alpha = *a;
10663         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10664         {
10665                 // generate color arrays for the surfaces in this list
10666                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10667                 {
10668                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10669                         int numverts = surface->num_vertices;
10670                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10671                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10672                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10673                         // q3-style directional shading
10674                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10675                         {
10676                                 if ((f = DotProduct(n, lightdir)) > 0)
10677                                         VectorMA(ambientcolor, f, diffusecolor, c);
10678                                 else
10679                                         VectorCopy(ambientcolor, c);
10680                                 c[3] = alpha;
10681                         }
10682                 }
10683                 *r = 1;
10684                 *g = 1;
10685                 *b = 1;
10686                 *a = 1;
10687                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10688                 rsurface.lightmapcolor4f_bufferobject = 0;
10689                 rsurface.lightmapcolor4f_bufferoffset = 0;
10690                 *applycolor = false;
10691         }
10692         else
10693         {
10694                 *r = ambientcolor[0];
10695                 *g = ambientcolor[1];
10696                 *b = ambientcolor[2];
10697                 rsurface.lightmapcolor4f = NULL;
10698                 rsurface.lightmapcolor4f_bufferobject = 0;
10699                 rsurface.lightmapcolor4f_bufferoffset = 0;
10700         }
10701 }
10702
10703 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10704 {
10705         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10706         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10707         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10708         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10709         GL_Color(r, g, b, a);
10710         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10711 }
10712
10713 void RSurf_SetupDepthAndCulling(void)
10714 {
10715         // submodels are biased to avoid z-fighting with world surfaces that they
10716         // may be exactly overlapping (avoids z-fighting artifacts on certain
10717         // doors and things in Quake maps)
10718         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10719         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10720         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10721         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10722 }
10723
10724 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10725 {
10726         // transparent sky would be ridiculous
10727         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10728                 return;
10729         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10730         skyrenderlater = true;
10731         RSurf_SetupDepthAndCulling();
10732         GL_DepthMask(true);
10733         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10734         // skymasking on them, and Quake3 never did sky masking (unlike
10735         // software Quake and software Quake2), so disable the sky masking
10736         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10737         // and skymasking also looks very bad when noclipping outside the
10738         // level, so don't use it then either.
10739         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10740         {
10741                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10742                 R_Mesh_ColorPointer(NULL, 0, 0);
10743                 R_Mesh_ResetTextureState();
10744                 if (skyrendermasked)
10745                 {
10746                         R_SetupShader_DepthOrShadow();
10747                         // depth-only (masking)
10748                         GL_ColorMask(0,0,0,0);
10749                         // just to make sure that braindead drivers don't draw
10750                         // anything despite that colormask...
10751                         GL_BlendFunc(GL_ZERO, GL_ONE);
10752                 }
10753                 else
10754                 {
10755                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10756                         // fog sky
10757                         GL_BlendFunc(GL_ONE, GL_ZERO);
10758                 }
10759                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10760                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10761                 if (skyrendermasked)
10762                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10763         }
10764         R_Mesh_ResetTextureState();
10765         GL_Color(1, 1, 1, 1);
10766 }
10767
10768 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10769 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10770 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10771 {
10772         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10773                 return;
10774         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10775         if (prepass)
10776         {
10777                 // render screenspace normalmap to texture
10778                 GL_DepthMask(true);
10779                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10780                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10781         }
10782         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10783         {
10784                 // render water or distortion background, then blend surface on top
10785                 GL_DepthMask(true);
10786                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10787                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10788                 GL_DepthMask(false);
10789                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10790                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10791                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10792                 else
10793                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10794         }
10795         else
10796         {
10797                 // render surface normally
10798                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10799                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10800                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10801                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10802                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10803                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10804                 else
10805                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10806         }
10807 }
10808
10809 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10810 {
10811         // OpenGL 1.3 path - anything not completely ancient
10812         int texturesurfaceindex;
10813         qboolean applycolor;
10814         qboolean applyfog;
10815         int layerindex;
10816         const texturelayer_t *layer;
10817         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10818
10819         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10820         {
10821                 vec4_t layercolor;
10822                 int layertexrgbscale;
10823                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10824                 {
10825                         if (layerindex == 0)
10826                                 GL_AlphaTest(true);
10827                         else
10828                         {
10829                                 GL_AlphaTest(false);
10830                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10831                         }
10832                 }
10833                 GL_DepthMask(layer->depthmask && writedepth);
10834                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10835                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10836                 {
10837                         layertexrgbscale = 4;
10838                         VectorScale(layer->color, 0.25f, layercolor);
10839                 }
10840                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10841                 {
10842                         layertexrgbscale = 2;
10843                         VectorScale(layer->color, 0.5f, layercolor);
10844                 }
10845                 else
10846                 {
10847                         layertexrgbscale = 1;
10848                         VectorScale(layer->color, 1.0f, layercolor);
10849                 }
10850                 layercolor[3] = layer->color[3];
10851                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10852                 R_Mesh_ColorPointer(NULL, 0, 0);
10853                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10854                 switch (layer->type)
10855                 {
10856                 case TEXTURELAYERTYPE_LITTEXTURE:
10857                         // single-pass lightmapped texture with 2x rgbscale
10858                         R_Mesh_TexBind(0, r_texture_white);
10859                         R_Mesh_TexMatrix(0, NULL);
10860                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10861                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10862                         R_Mesh_TexBind(1, layer->texture);
10863                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10864                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10865                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10866                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10867                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10868                         else if (rsurface.uselightmaptexture)
10869                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10870                         else
10871                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10872                         break;
10873                 case TEXTURELAYERTYPE_TEXTURE:
10874                         // singletexture unlit texture with transparency support
10875                         R_Mesh_TexBind(0, layer->texture);
10876                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10877                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10878                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10879                         R_Mesh_TexBind(1, 0);
10880                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10881                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10882                         break;
10883                 case TEXTURELAYERTYPE_FOG:
10884                         // singletexture fogging
10885                         if (layer->texture)
10886                         {
10887                                 R_Mesh_TexBind(0, layer->texture);
10888                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10889                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10890                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10891                         }
10892                         else
10893                         {
10894                                 R_Mesh_TexBind(0, 0);
10895                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10896                         }
10897                         R_Mesh_TexBind(1, 0);
10898                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10899                         // generate a color array for the fog pass
10900                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10901                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10902                         {
10903                                 int i;
10904                                 float f;
10905                                 const float *v;
10906                                 float *c;
10907                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10908                                 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)
10909                                 {
10910                                         f = 1 - RSurf_FogVertex(v);
10911                                         c[0] = layercolor[0];
10912                                         c[1] = layercolor[1];
10913                                         c[2] = layercolor[2];
10914                                         c[3] = f * layercolor[3];
10915                                 }
10916                         }
10917                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10918                         break;
10919                 default:
10920                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10921                 }
10922         }
10923         CHECKGLERROR
10924         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10925         {
10926                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10927                 GL_AlphaTest(false);
10928         }
10929 }
10930
10931 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10932 {
10933         // OpenGL 1.1 - crusty old voodoo path
10934         int texturesurfaceindex;
10935         qboolean applyfog;
10936         int layerindex;
10937         const texturelayer_t *layer;
10938         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10939
10940         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10941         {
10942                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10943                 {
10944                         if (layerindex == 0)
10945                                 GL_AlphaTest(true);
10946                         else
10947                         {
10948                                 GL_AlphaTest(false);
10949                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10950                         }
10951                 }
10952                 GL_DepthMask(layer->depthmask && writedepth);
10953                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10954                 R_Mesh_ColorPointer(NULL, 0, 0);
10955                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10956                 switch (layer->type)
10957                 {
10958                 case TEXTURELAYERTYPE_LITTEXTURE:
10959                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10960                         {
10961                                 // two-pass lit texture with 2x rgbscale
10962                                 // first the lightmap pass
10963                                 R_Mesh_TexBind(0, r_texture_white);
10964                                 R_Mesh_TexMatrix(0, NULL);
10965                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10966                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10967                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10968                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10969                                 else if (rsurface.uselightmaptexture)
10970                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10971                                 else
10972                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10973                                 // then apply the texture to it
10974                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10975                                 R_Mesh_TexBind(0, layer->texture);
10976                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10977                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10978                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10979                                 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);
10980                         }
10981                         else
10982                         {
10983                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10984                                 R_Mesh_TexBind(0, layer->texture);
10985                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10986                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10987                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10988                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10989                                         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);
10990                                 else
10991                                         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);
10992                         }
10993                         break;
10994                 case TEXTURELAYERTYPE_TEXTURE:
10995                         // singletexture unlit texture with transparency support
10996                         R_Mesh_TexBind(0, layer->texture);
10997                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10998                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10999                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11000                         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);
11001                         break;
11002                 case TEXTURELAYERTYPE_FOG:
11003                         // singletexture fogging
11004                         if (layer->texture)
11005                         {
11006                                 R_Mesh_TexBind(0, layer->texture);
11007                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11008                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11009                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
11010                         }
11011                         else
11012                         {
11013                                 R_Mesh_TexBind(0, 0);
11014                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
11015                         }
11016                         // generate a color array for the fog pass
11017                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
11018                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11019                         {
11020                                 int i;
11021                                 float f;
11022                                 const float *v;
11023                                 float *c;
11024                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
11025                                 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)
11026                                 {
11027                                         f = 1 - RSurf_FogVertex(v);
11028                                         c[0] = layer->color[0];
11029                                         c[1] = layer->color[1];
11030                                         c[2] = layer->color[2];
11031                                         c[3] = f * layer->color[3];
11032                                 }
11033                         }
11034                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11035                         break;
11036                 default:
11037                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11038                 }
11039         }
11040         CHECKGLERROR
11041         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11042         {
11043                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11044                 GL_AlphaTest(false);
11045         }
11046 }
11047
11048 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11049 {
11050         float c[4];
11051
11052         GL_AlphaTest(false);
11053         R_Mesh_ColorPointer(NULL, 0, 0);
11054         R_Mesh_ResetTextureState();
11055         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11056
11057         if(rsurface.texture && rsurface.texture->currentskinframe)
11058         {
11059                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11060                 c[3] *= rsurface.texture->currentalpha;
11061         }
11062         else
11063         {
11064                 c[0] = 1;
11065                 c[1] = 0;
11066                 c[2] = 1;
11067                 c[3] = 1;
11068         }
11069
11070         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11071         {
11072                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11073                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11074                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11075         }
11076
11077         // brighten it up (as texture value 127 means "unlit")
11078         c[0] *= 2 * r_refdef.view.colorscale;
11079         c[1] *= 2 * r_refdef.view.colorscale;
11080         c[2] *= 2 * r_refdef.view.colorscale;
11081
11082         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11083                 c[3] *= r_wateralpha.value;
11084
11085         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11086         {
11087                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11088                 GL_DepthMask(false);
11089         }
11090         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11091         {
11092                 GL_BlendFunc(GL_ONE, GL_ONE);
11093                 GL_DepthMask(false);
11094         }
11095         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11096         {
11097                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11098                 GL_DepthMask(false);
11099         }
11100         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11101         {
11102                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11103                 GL_DepthMask(false);
11104         }
11105         else
11106         {
11107                 GL_BlendFunc(GL_ONE, GL_ZERO);
11108                 GL_DepthMask(writedepth);
11109         }
11110
11111         rsurface.lightmapcolor4f = NULL;
11112
11113         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11114         {
11115                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11116
11117                 rsurface.lightmapcolor4f = NULL;
11118                 rsurface.lightmapcolor4f_bufferobject = 0;
11119                 rsurface.lightmapcolor4f_bufferoffset = 0;
11120         }
11121         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11122         {
11123                 qboolean applycolor = true;
11124                 float one = 1.0;
11125
11126                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11127
11128                 r_refdef.lightmapintensity = 1;
11129                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11130                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11131         }
11132         else
11133         {
11134                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11135
11136                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11137                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11138                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11139         }
11140
11141         if(!rsurface.lightmapcolor4f)
11142                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11143
11144         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11145         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11146         if(r_refdef.fogenabled)
11147                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11148
11149         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11150         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11151 }
11152
11153 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11154 {
11155         CHECKGLERROR
11156         RSurf_SetupDepthAndCulling();
11157         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11158         {
11159                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11160                 return;
11161         }
11162         switch (vid.renderpath)
11163         {
11164         case RENDERPATH_GL20:
11165         case RENDERPATH_CGGL:
11166                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11167                 break;
11168         case RENDERPATH_GL13:
11169                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11170                 break;
11171         case RENDERPATH_GL11:
11172                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11173                 break;
11174         }
11175         CHECKGLERROR
11176 }
11177
11178 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11179 {
11180         CHECKGLERROR
11181         RSurf_SetupDepthAndCulling();
11182         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11183         {
11184                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11185                 return;
11186         }
11187         switch (vid.renderpath)
11188         {
11189         case RENDERPATH_GL20:
11190         case RENDERPATH_CGGL:
11191                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11192                 break;
11193         case RENDERPATH_GL13:
11194                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11195                 break;
11196         case RENDERPATH_GL11:
11197                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11198                 break;
11199         }
11200         CHECKGLERROR
11201 }
11202
11203 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11204 {
11205         int i, j;
11206         int texturenumsurfaces, endsurface;
11207         texture_t *texture;
11208         const msurface_t *surface;
11209         const msurface_t *texturesurfacelist[256];
11210
11211         // if the model is static it doesn't matter what value we give for
11212         // wantnormals and wanttangents, so this logic uses only rules applicable
11213         // to a model, knowing that they are meaningless otherwise
11214         if (ent == r_refdef.scene.worldentity)
11215                 RSurf_ActiveWorldEntity();
11216         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11217                 RSurf_ActiveModelEntity(ent, false, false, false);
11218         else
11219         {
11220                 switch (vid.renderpath)
11221                 {
11222                 case RENDERPATH_GL20:
11223                 case RENDERPATH_CGGL:
11224                         RSurf_ActiveModelEntity(ent, true, true, false);
11225                         break;
11226                 case RENDERPATH_GL13:
11227                 case RENDERPATH_GL11:
11228                         RSurf_ActiveModelEntity(ent, true, false, false);
11229                         break;
11230                 }
11231         }
11232
11233         if (r_transparentdepthmasking.integer)
11234         {
11235                 qboolean setup = false;
11236                 for (i = 0;i < numsurfaces;i = j)
11237                 {
11238                         j = i + 1;
11239                         surface = rsurface.modelsurfaces + surfacelist[i];
11240                         texture = surface->texture;
11241                         rsurface.texture = R_GetCurrentTexture(texture);
11242                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11243                         // scan ahead until we find a different texture
11244                         endsurface = min(i + 1024, numsurfaces);
11245                         texturenumsurfaces = 0;
11246                         texturesurfacelist[texturenumsurfaces++] = surface;
11247                         for (;j < endsurface;j++)
11248                         {
11249                                 surface = rsurface.modelsurfaces + surfacelist[j];
11250                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11251                                         break;
11252                                 texturesurfacelist[texturenumsurfaces++] = surface;
11253                         }
11254                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11255                                 continue;
11256                         // render the range of surfaces as depth
11257                         if (!setup)
11258                         {
11259                                 setup = true;
11260                                 GL_ColorMask(0,0,0,0);
11261                                 GL_Color(1,1,1,1);
11262                                 GL_DepthTest(true);
11263                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11264                                 GL_DepthMask(true);
11265                                 GL_AlphaTest(false);
11266                                 R_Mesh_ColorPointer(NULL, 0, 0);
11267                                 R_Mesh_ResetTextureState();
11268                                 R_SetupShader_DepthOrShadow();
11269                         }
11270                         RSurf_SetupDepthAndCulling();
11271                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11272                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11273                 }
11274                 if (setup)
11275                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11276         }
11277
11278         for (i = 0;i < numsurfaces;i = j)
11279         {
11280                 j = i + 1;
11281                 surface = rsurface.modelsurfaces + surfacelist[i];
11282                 texture = surface->texture;
11283                 rsurface.texture = R_GetCurrentTexture(texture);
11284                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11285                 // scan ahead until we find a different texture
11286                 endsurface = min(i + 1024, numsurfaces);
11287                 texturenumsurfaces = 0;
11288                 texturesurfacelist[texturenumsurfaces++] = surface;
11289                 for (;j < endsurface;j++)
11290                 {
11291                         surface = rsurface.modelsurfaces + surfacelist[j];
11292                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11293                                 break;
11294                         texturesurfacelist[texturenumsurfaces++] = surface;
11295                 }
11296                 // render the range of surfaces
11297                 if (ent == r_refdef.scene.worldentity)
11298                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11299                 else
11300                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11301         }
11302         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11303         GL_AlphaTest(false);
11304 }
11305
11306 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11307 {
11308         // transparent surfaces get pushed off into the transparent queue
11309         int surfacelistindex;
11310         const msurface_t *surface;
11311         vec3_t tempcenter, center;
11312         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11313         {
11314                 surface = texturesurfacelist[surfacelistindex];
11315                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11316                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11317                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11318                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11319                 if (queueentity->transparent_offset) // transparent offset
11320                 {
11321                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11322                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11323                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11324                 }
11325                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11326         }
11327 }
11328
11329 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11330 {
11331         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11332         CHECKGLERROR
11333         if (depthonly)
11334         {
11335                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11336                         return;
11337                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11338                         return;
11339                 RSurf_SetupDepthAndCulling();
11340                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11341                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11342         }
11343         else if (prepass)
11344         {
11345                 if (!rsurface.texture->currentnumlayers)
11346                         return;
11347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11348                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11349                 else
11350                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11351         }
11352         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11353         {
11354                 RSurf_SetupDepthAndCulling();
11355                 GL_AlphaTest(false);
11356                 R_Mesh_ColorPointer(NULL, 0, 0);
11357                 R_Mesh_ResetTextureState();
11358                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11359                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11360                 GL_DepthMask(true);
11361                 GL_BlendFunc(GL_ONE, GL_ZERO);
11362                 GL_Color(0, 0, 0, 1);
11363                 GL_DepthTest(writedepth);
11364                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11365         }
11366         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11367         {
11368                 RSurf_SetupDepthAndCulling();
11369                 GL_AlphaTest(false);
11370                 R_Mesh_ColorPointer(NULL, 0, 0);
11371                 R_Mesh_ResetTextureState();
11372                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11373                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11374                 GL_DepthMask(true);
11375                 GL_BlendFunc(GL_ONE, GL_ZERO);
11376                 GL_DepthTest(true);
11377                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11378         }
11379         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11380                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11381         else if (!rsurface.texture->currentnumlayers)
11382                 return;
11383         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11384         {
11385                 // in the deferred case, transparent surfaces were queued during prepass
11386                 if (!r_shadow_usingdeferredprepass)
11387                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11388         }
11389         else
11390         {
11391                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11392                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11393         }
11394         CHECKGLERROR
11395 }
11396
11397 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11398 {
11399         int i, j;
11400         texture_t *texture;
11401         // break the surface list down into batches by texture and use of lightmapping
11402         for (i = 0;i < numsurfaces;i = j)
11403         {
11404                 j = i + 1;
11405                 // texture is the base texture pointer, rsurface.texture is the
11406                 // current frame/skin the texture is directing us to use (for example
11407                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11408                 // use skin 1 instead)
11409                 texture = surfacelist[i]->texture;
11410                 rsurface.texture = R_GetCurrentTexture(texture);
11411                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11412                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11413                 {
11414                         // if this texture is not the kind we want, skip ahead to the next one
11415                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11416                                 ;
11417                         continue;
11418                 }
11419                 // simply scan ahead until we find a different texture or lightmap state
11420                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11421                         ;
11422                 // render the range of surfaces
11423                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11424         }
11425 }
11426
11427 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11428 {
11429         CHECKGLERROR
11430         if (depthonly)
11431         {
11432                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11433                         return;
11434                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11435                         return;
11436                 RSurf_SetupDepthAndCulling();
11437                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11438                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11439         }
11440         else if (prepass)
11441         {
11442                 if (!rsurface.texture->currentnumlayers)
11443                         return;
11444                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11445                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11446                 else
11447                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11448         }
11449         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11450         {
11451                 RSurf_SetupDepthAndCulling();
11452                 GL_AlphaTest(false);
11453                 R_Mesh_ColorPointer(NULL, 0, 0);
11454                 R_Mesh_ResetTextureState();
11455                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11456                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11457                 GL_DepthMask(true);
11458                 GL_BlendFunc(GL_ONE, GL_ZERO);
11459                 GL_Color(0, 0, 0, 1);
11460                 GL_DepthTest(writedepth);
11461                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11462         }
11463         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11464         {
11465                 RSurf_SetupDepthAndCulling();
11466                 GL_AlphaTest(false);
11467                 R_Mesh_ColorPointer(NULL, 0, 0);
11468                 R_Mesh_ResetTextureState();
11469                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11470                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11471                 GL_DepthMask(true);
11472                 GL_BlendFunc(GL_ONE, GL_ZERO);
11473                 GL_DepthTest(true);
11474                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11475         }
11476         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11477                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11478         else if (!rsurface.texture->currentnumlayers)
11479                 return;
11480         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11481         {
11482                 // in the deferred case, transparent surfaces were queued during prepass
11483                 if (!r_shadow_usingdeferredprepass)
11484                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11485         }
11486         else
11487         {
11488                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11489                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11490         }
11491         CHECKGLERROR
11492 }
11493
11494 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11495 {
11496         int i, j;
11497         texture_t *texture;
11498         // break the surface list down into batches by texture and use of lightmapping
11499         for (i = 0;i < numsurfaces;i = j)
11500         {
11501                 j = i + 1;
11502                 // texture is the base texture pointer, rsurface.texture is the
11503                 // current frame/skin the texture is directing us to use (for example
11504                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11505                 // use skin 1 instead)
11506                 texture = surfacelist[i]->texture;
11507                 rsurface.texture = R_GetCurrentTexture(texture);
11508                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11509                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11510                 {
11511                         // if this texture is not the kind we want, skip ahead to the next one
11512                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11513                                 ;
11514                         continue;
11515                 }
11516                 // simply scan ahead until we find a different texture or lightmap state
11517                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11518                         ;
11519                 // render the range of surfaces
11520                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11521         }
11522 }
11523
11524 float locboxvertex3f[6*4*3] =
11525 {
11526         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11527         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11528         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11529         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11530         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11531         1,0,0, 0,0,0, 0,1,0, 1,1,0
11532 };
11533
11534 unsigned short locboxelements[6*2*3] =
11535 {
11536          0, 1, 2, 0, 2, 3,
11537          4, 5, 6, 4, 6, 7,
11538          8, 9,10, 8,10,11,
11539         12,13,14, 12,14,15,
11540         16,17,18, 16,18,19,
11541         20,21,22, 20,22,23
11542 };
11543
11544 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11545 {
11546         int i, j;
11547         cl_locnode_t *loc = (cl_locnode_t *)ent;
11548         vec3_t mins, size;
11549         float vertex3f[6*4*3];
11550         CHECKGLERROR
11551         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11552         GL_DepthMask(false);
11553         GL_DepthRange(0, 1);
11554         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11555         GL_DepthTest(true);
11556         GL_CullFace(GL_NONE);
11557         R_EntityMatrix(&identitymatrix);
11558
11559         R_Mesh_VertexPointer(vertex3f, 0, 0);
11560         R_Mesh_ColorPointer(NULL, 0, 0);
11561         R_Mesh_ResetTextureState();
11562         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11563
11564         i = surfacelist[0];
11565         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11566                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11567                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11568                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11569
11570         if (VectorCompare(loc->mins, loc->maxs))
11571         {
11572                 VectorSet(size, 2, 2, 2);
11573                 VectorMA(loc->mins, -0.5f, size, mins);
11574         }
11575         else
11576         {
11577                 VectorCopy(loc->mins, mins);
11578                 VectorSubtract(loc->maxs, loc->mins, size);
11579         }
11580
11581         for (i = 0;i < 6*4*3;)
11582                 for (j = 0;j < 3;j++, i++)
11583                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11584
11585         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11586 }
11587
11588 void R_DrawLocs(void)
11589 {
11590         int index;
11591         cl_locnode_t *loc, *nearestloc;
11592         vec3_t center;
11593         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11594         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11595         {
11596                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11597                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11598         }
11599 }
11600
11601 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11602 {
11603         if (decalsystem->decals)
11604                 Mem_Free(decalsystem->decals);
11605         memset(decalsystem, 0, sizeof(*decalsystem));
11606 }
11607
11608 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)
11609 {
11610         tridecal_t *decal;
11611         tridecal_t *decals;
11612         int i;
11613
11614         // expand or initialize the system
11615         if (decalsystem->maxdecals <= decalsystem->numdecals)
11616         {
11617                 decalsystem_t old = *decalsystem;
11618                 qboolean useshortelements;
11619                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11620                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11621                 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)));
11622                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11623                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11624                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11625                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11626                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11627                 if (decalsystem->numdecals)
11628                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11629                 if (old.decals)
11630                         Mem_Free(old.decals);
11631                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11632                         decalsystem->element3i[i] = i;
11633                 if (useshortelements)
11634                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11635                                 decalsystem->element3s[i] = i;
11636         }
11637
11638         // grab a decal and search for another free slot for the next one
11639         decals = decalsystem->decals;
11640         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11641         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11642                 ;
11643         decalsystem->freedecal = i;
11644         if (decalsystem->numdecals <= i)
11645                 decalsystem->numdecals = i + 1;
11646
11647         // initialize the decal
11648         decal->lived = 0;
11649         decal->triangleindex = triangleindex;
11650         decal->surfaceindex = surfaceindex;
11651         decal->decalsequence = decalsequence;
11652         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11653         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11654         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11655         decal->color4ub[0][3] = 255;
11656         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11657         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11658         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11659         decal->color4ub[1][3] = 255;
11660         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11661         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11662         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11663         decal->color4ub[2][3] = 255;
11664         decal->vertex3f[0][0] = v0[0];
11665         decal->vertex3f[0][1] = v0[1];
11666         decal->vertex3f[0][2] = v0[2];
11667         decal->vertex3f[1][0] = v1[0];
11668         decal->vertex3f[1][1] = v1[1];
11669         decal->vertex3f[1][2] = v1[2];
11670         decal->vertex3f[2][0] = v2[0];
11671         decal->vertex3f[2][1] = v2[1];
11672         decal->vertex3f[2][2] = v2[2];
11673         decal->texcoord2f[0][0] = t0[0];
11674         decal->texcoord2f[0][1] = t0[1];
11675         decal->texcoord2f[1][0] = t1[0];
11676         decal->texcoord2f[1][1] = t1[1];
11677         decal->texcoord2f[2][0] = t2[0];
11678         decal->texcoord2f[2][1] = t2[1];
11679 }
11680
11681 extern cvar_t cl_decals_bias;
11682 extern cvar_t cl_decals_models;
11683 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11684 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)
11685 {
11686         matrix4x4_t projection;
11687         decalsystem_t *decalsystem;
11688         qboolean dynamic;
11689         dp_model_t *model;
11690         const float *vertex3f;
11691         const msurface_t *surface;
11692         const msurface_t *surfaces;
11693         const int *surfacelist;
11694         const texture_t *texture;
11695         int numtriangles;
11696         int numsurfacelist;
11697         int surfacelistindex;
11698         int surfaceindex;
11699         int triangleindex;
11700         int cornerindex;
11701         int index;
11702         int numpoints;
11703         const int *e;
11704         float localorigin[3];
11705         float localnormal[3];
11706         float localmins[3];
11707         float localmaxs[3];
11708         float localsize;
11709         float v[9][3];
11710         float tc[9][2];
11711         float c[9][4];
11712         //float normal[3];
11713         float planes[6][4];
11714         float f;
11715         float points[2][9][3];
11716         float angles[3];
11717         float temp[3];
11718
11719         decalsystem = &ent->decalsystem;
11720         model = ent->model;
11721         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11722         {
11723                 R_DecalSystem_Reset(&ent->decalsystem);
11724                 return;
11725         }
11726
11727         if (!model->brush.data_nodes && !cl_decals_models.integer)
11728         {
11729                 if (decalsystem->model)
11730                         R_DecalSystem_Reset(decalsystem);
11731                 return;
11732         }
11733
11734         if (decalsystem->model != model)
11735                 R_DecalSystem_Reset(decalsystem);
11736         decalsystem->model = model;
11737
11738         RSurf_ActiveModelEntity(ent, false, false, false);
11739
11740         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11741         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11742         VectorNormalize(localnormal);
11743         localsize = worldsize*rsurface.inversematrixscale;
11744         localmins[0] = localorigin[0] - localsize;
11745         localmins[1] = localorigin[1] - localsize;
11746         localmins[2] = localorigin[2] - localsize;
11747         localmaxs[0] = localorigin[0] + localsize;
11748         localmaxs[1] = localorigin[1] + localsize;
11749         localmaxs[2] = localorigin[2] + localsize;
11750
11751         //VectorCopy(localnormal, planes[4]);
11752         //VectorVectors(planes[4], planes[2], planes[0]);
11753         AnglesFromVectors(angles, localnormal, NULL, false);
11754         AngleVectors(angles, planes[0], planes[2], planes[4]);
11755         VectorNegate(planes[0], planes[1]);
11756         VectorNegate(planes[2], planes[3]);
11757         VectorNegate(planes[4], planes[5]);
11758         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11759         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11760         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11761         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11762         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11763         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11764
11765 #if 1
11766 // works
11767 {
11768         matrix4x4_t forwardprojection;
11769         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11770         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11771 }
11772 #else
11773 // broken
11774 {
11775         float projectionvector[4][3];
11776         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11777         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11778         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11779         projectionvector[0][0] = planes[0][0] * ilocalsize;
11780         projectionvector[0][1] = planes[1][0] * ilocalsize;
11781         projectionvector[0][2] = planes[2][0] * ilocalsize;
11782         projectionvector[1][0] = planes[0][1] * ilocalsize;
11783         projectionvector[1][1] = planes[1][1] * ilocalsize;
11784         projectionvector[1][2] = planes[2][1] * ilocalsize;
11785         projectionvector[2][0] = planes[0][2] * ilocalsize;
11786         projectionvector[2][1] = planes[1][2] * ilocalsize;
11787         projectionvector[2][2] = planes[2][2] * ilocalsize;
11788         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11789         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11790         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11791         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11792 }
11793 #endif
11794
11795         dynamic = model->surfmesh.isanimated;
11796         vertex3f = rsurface.modelvertex3f;
11797         numsurfacelist = model->nummodelsurfaces;
11798         surfacelist = model->sortedmodelsurfaces;
11799         surfaces = model->data_surfaces;
11800         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11801         {
11802                 surfaceindex = surfacelist[surfacelistindex];
11803                 surface = surfaces + surfaceindex;
11804                 // check cull box first because it rejects more than any other check
11805                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11806                         continue;
11807                 // skip transparent surfaces
11808                 texture = surface->texture;
11809                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11810                         continue;
11811                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11812                         continue;
11813                 numtriangles = surface->num_triangles;
11814                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11815                 {
11816                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11817                         {
11818                                 index = 3*e[cornerindex];
11819                                 VectorCopy(vertex3f + index, v[cornerindex]);
11820                         }
11821                         // cull backfaces
11822                         //TriangleNormal(v[0], v[1], v[2], normal);
11823                         //if (DotProduct(normal, localnormal) < 0.0f)
11824                         //      continue;
11825                         // clip by each of the box planes formed from the projection matrix
11826                         // if anything survives, we emit the decal
11827                         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]);
11828                         if (numpoints < 3)
11829                                 continue;
11830                         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]);
11831                         if (numpoints < 3)
11832                                 continue;
11833                         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]);
11834                         if (numpoints < 3)
11835                                 continue;
11836                         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]);
11837                         if (numpoints < 3)
11838                                 continue;
11839                         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]);
11840                         if (numpoints < 3)
11841                                 continue;
11842                         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]);
11843                         if (numpoints < 3)
11844                                 continue;
11845                         // some part of the triangle survived, so we have to accept it...
11846                         if (dynamic)
11847                         {
11848                                 // dynamic always uses the original triangle
11849                                 numpoints = 3;
11850                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11851                                 {
11852                                         index = 3*e[cornerindex];
11853                                         VectorCopy(vertex3f + index, v[cornerindex]);
11854                                 }
11855                         }
11856                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11857                         {
11858                                 // convert vertex positions to texcoords
11859                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11860                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11861                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11862                                 // calculate distance fade from the projection origin
11863                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11864                                 f = bound(0.0f, f, 1.0f);
11865                                 c[cornerindex][0] = r * f;
11866                                 c[cornerindex][1] = g * f;
11867                                 c[cornerindex][2] = b * f;
11868                                 c[cornerindex][3] = 1.0f;
11869                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11870                         }
11871                         if (dynamic)
11872                                 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);
11873                         else
11874                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11875                                         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);
11876                 }
11877         }
11878 }
11879
11880 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11881 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)
11882 {
11883         int renderentityindex;
11884         float worldmins[3];
11885         float worldmaxs[3];
11886         entity_render_t *ent;
11887
11888         if (!cl_decals_newsystem.integer)
11889                 return;
11890
11891         worldmins[0] = worldorigin[0] - worldsize;
11892         worldmins[1] = worldorigin[1] - worldsize;
11893         worldmins[2] = worldorigin[2] - worldsize;
11894         worldmaxs[0] = worldorigin[0] + worldsize;
11895         worldmaxs[1] = worldorigin[1] + worldsize;
11896         worldmaxs[2] = worldorigin[2] + worldsize;
11897
11898         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11899
11900         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11901         {
11902                 ent = r_refdef.scene.entities[renderentityindex];
11903                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11904                         continue;
11905
11906                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11907         }
11908 }
11909
11910 typedef struct r_decalsystem_splatqueue_s
11911 {
11912         vec3_t worldorigin;
11913         vec3_t worldnormal;
11914         float color[4];
11915         float tcrange[4];
11916         float worldsize;
11917         int decalsequence;
11918 }
11919 r_decalsystem_splatqueue_t;
11920
11921 int r_decalsystem_numqueued = 0;
11922 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11923
11924 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)
11925 {
11926         r_decalsystem_splatqueue_t *queue;
11927
11928         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11929                 return;
11930
11931         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11932         VectorCopy(worldorigin, queue->worldorigin);
11933         VectorCopy(worldnormal, queue->worldnormal);
11934         Vector4Set(queue->color, r, g, b, a);
11935         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11936         queue->worldsize = worldsize;
11937         queue->decalsequence = cl.decalsequence++;
11938 }
11939
11940 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11941 {
11942         int i;
11943         r_decalsystem_splatqueue_t *queue;
11944
11945         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11946                 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);
11947         r_decalsystem_numqueued = 0;
11948 }
11949
11950 extern cvar_t cl_decals_max;
11951 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11952 {
11953         int i;
11954         decalsystem_t *decalsystem = &ent->decalsystem;
11955         int numdecals;
11956         int killsequence;
11957         tridecal_t *decal;
11958         float frametime;
11959         float lifetime;
11960
11961         if (!decalsystem->numdecals)
11962                 return;
11963
11964         if (r_showsurfaces.integer)
11965                 return;
11966
11967         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11968         {
11969                 R_DecalSystem_Reset(decalsystem);
11970                 return;
11971         }
11972
11973         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11974         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11975
11976         if (decalsystem->lastupdatetime)
11977                 frametime = (cl.time - decalsystem->lastupdatetime);
11978         else
11979                 frametime = 0;
11980         decalsystem->lastupdatetime = cl.time;
11981         decal = decalsystem->decals;
11982         numdecals = decalsystem->numdecals;
11983
11984         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11985         {
11986                 if (decal->color4ub[0][3])
11987                 {
11988                         decal->lived += frametime;
11989                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11990                         {
11991                                 memset(decal, 0, sizeof(*decal));
11992                                 if (decalsystem->freedecal > i)
11993                                         decalsystem->freedecal = i;
11994                         }
11995                 }
11996         }
11997         decal = decalsystem->decals;
11998         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11999                 numdecals--;
12000
12001         // collapse the array by shuffling the tail decals into the gaps
12002         for (;;)
12003         {
12004                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12005                         decalsystem->freedecal++;
12006                 if (decalsystem->freedecal == numdecals)
12007                         break;
12008                 decal[decalsystem->freedecal] = decal[--numdecals];
12009         }
12010
12011         decalsystem->numdecals = numdecals;
12012
12013         if (numdecals <= 0)
12014         {
12015                 // if there are no decals left, reset decalsystem
12016                 R_DecalSystem_Reset(decalsystem);
12017         }
12018 }
12019
12020 extern skinframe_t *decalskinframe;
12021 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12022 {
12023         int i;
12024         decalsystem_t *decalsystem = &ent->decalsystem;
12025         int numdecals;
12026         tridecal_t *decal;
12027         float faderate;
12028         float alpha;
12029         float *v3f;
12030         float *c4f;
12031         float *t2f;
12032         const int *e;
12033         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12034         int numtris = 0;
12035
12036         numdecals = decalsystem->numdecals;
12037         if (!numdecals)
12038                 return;
12039
12040         if (r_showsurfaces.integer)
12041                 return;
12042
12043         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12044         {
12045                 R_DecalSystem_Reset(decalsystem);
12046                 return;
12047         }
12048
12049         // if the model is static it doesn't matter what value we give for
12050         // wantnormals and wanttangents, so this logic uses only rules applicable
12051         // to a model, knowing that they are meaningless otherwise
12052         if (ent == r_refdef.scene.worldentity)
12053                 RSurf_ActiveWorldEntity();
12054         else
12055                 RSurf_ActiveModelEntity(ent, false, false, false);
12056
12057         decalsystem->lastupdatetime = cl.time;
12058         decal = decalsystem->decals;
12059
12060         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12061
12062         // update vertex positions for animated models
12063         v3f = decalsystem->vertex3f;
12064         c4f = decalsystem->color4f;
12065         t2f = decalsystem->texcoord2f;
12066         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12067         {
12068                 if (!decal->color4ub[0][3])
12069                         continue;
12070
12071                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12072                         continue;
12073
12074                 // update color values for fading decals
12075                 if (decal->lived >= cl_decals_time.value)
12076                 {
12077                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12078                         alpha *= (1.0f/255.0f);
12079                 }
12080                 else
12081                         alpha = 1.0f/255.0f;
12082
12083                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12084                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12085                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12086                 c4f[ 3] = 1;
12087                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12088                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12089                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12090                 c4f[ 7] = 1;
12091                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12092                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12093                 c4f[10] = decal->color4ub[2][2] * alpha;
12094                 c4f[11] = 1;
12095
12096                 t2f[0] = decal->texcoord2f[0][0];
12097                 t2f[1] = decal->texcoord2f[0][1];
12098                 t2f[2] = decal->texcoord2f[1][0];
12099                 t2f[3] = decal->texcoord2f[1][1];
12100                 t2f[4] = decal->texcoord2f[2][0];
12101                 t2f[5] = decal->texcoord2f[2][1];
12102
12103                 // update vertex positions for animated models
12104                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12105                 {
12106                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12107                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12108                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12109                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12110                 }
12111                 else
12112                 {
12113                         VectorCopy(decal->vertex3f[0], v3f);
12114                         VectorCopy(decal->vertex3f[1], v3f + 3);
12115                         VectorCopy(decal->vertex3f[2], v3f + 6);
12116                 }
12117
12118                 if (r_refdef.fogenabled)
12119                 {
12120                         alpha = RSurf_FogVertex(v3f);
12121                         VectorScale(c4f, alpha, c4f);
12122                         alpha = RSurf_FogVertex(v3f + 3);
12123                         VectorScale(c4f + 4, alpha, c4f + 4);
12124                         alpha = RSurf_FogVertex(v3f + 6);
12125                         VectorScale(c4f + 8, alpha, c4f + 8);
12126                 }
12127
12128                 v3f += 9;
12129                 c4f += 12;
12130                 t2f += 6;
12131                 numtris++;
12132         }
12133
12134         if (numtris > 0)
12135         {
12136                 r_refdef.stats.drawndecals += numtris;
12137
12138                 // now render the decals all at once
12139                 // (this assumes they all use one particle font texture!)
12140                 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);
12141                 R_Mesh_ResetTextureState();
12142                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12143                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12144                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12145                 GL_DepthMask(false);
12146                 GL_DepthRange(0, 1);
12147                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12148                 GL_DepthTest(true);
12149                 GL_CullFace(GL_NONE);
12150                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12151                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12152                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12153         }
12154 }
12155
12156 static void R_DrawModelDecals(void)
12157 {
12158         int i, numdecals;
12159
12160         // fade faster when there are too many decals
12161         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12162         for (i = 0;i < r_refdef.scene.numentities;i++)
12163                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12164
12165         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12166         for (i = 0;i < r_refdef.scene.numentities;i++)
12167                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12168                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12169
12170         R_DecalSystem_ApplySplatEntitiesQueue();
12171
12172         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12173         for (i = 0;i < r_refdef.scene.numentities;i++)
12174                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12175
12176         r_refdef.stats.totaldecals += numdecals;
12177
12178         if (r_showsurfaces.integer)
12179                 return;
12180
12181         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12182
12183         for (i = 0;i < r_refdef.scene.numentities;i++)
12184         {
12185                 if (!r_refdef.viewcache.entityvisible[i])
12186                         continue;
12187                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12188                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12189         }
12190 }
12191
12192 extern cvar_t mod_collision_bih;
12193 void R_DrawDebugModel(void)
12194 {
12195         entity_render_t *ent = rsurface.entity;
12196         int i, j, k, l, flagsmask;
12197         const msurface_t *surface;
12198         dp_model_t *model = ent->model;
12199         vec3_t v;
12200
12201         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12202
12203         R_Mesh_ColorPointer(NULL, 0, 0);
12204         R_Mesh_ResetTextureState();
12205         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12206         GL_DepthRange(0, 1);
12207         GL_DepthTest(!r_showdisabledepthtest.integer);
12208         GL_DepthMask(false);
12209         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12210
12211         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12212         {
12213                 int triangleindex;
12214                 int bihleafindex;
12215                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12216                 const q3mbrush_t *brush;
12217                 const bih_t *bih = &model->collision_bih;
12218                 const bih_leaf_t *bihleaf;
12219                 float vertex3f[3][3];
12220                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12221                 cullbox = false;
12222                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12223                 {
12224                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12225                                 continue;
12226                         switch (bihleaf->type)
12227                         {
12228                         case BIH_BRUSH:
12229                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12230                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12231                                 {
12232                                         R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12233                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12234                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12235                                 }
12236                                 break;
12237                         case BIH_COLLISIONTRIANGLE:
12238                                 triangleindex = bihleaf->itemindex;
12239                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12240                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12241                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12242                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12243                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12244                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12245                                 break;
12246                         case BIH_RENDERTRIANGLE:
12247                                 triangleindex = bihleaf->itemindex;
12248                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12249                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12250                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12251                                 R_Mesh_VertexPointer(vertex3f[0], 0, 0);
12252                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12253                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, polygonelement3s, 0, 0);
12254                                 break;
12255                         }
12256                 }
12257         }
12258
12259         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12260
12261         if (r_showtris.integer || r_shownormals.integer)
12262         {
12263                 if (r_showdisabledepthtest.integer)
12264                 {
12265                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12266                         GL_DepthMask(false);
12267                 }
12268                 else
12269                 {
12270                         GL_BlendFunc(GL_ONE, GL_ZERO);
12271                         GL_DepthMask(true);
12272                 }
12273                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12274                 {
12275                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12276                                 continue;
12277                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12278                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12279                         {
12280                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12281                                 if (r_showtris.value > 0)
12282                                 {
12283                                         if (!rsurface.texture->currentlayers->depthmask)
12284                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12285                                         else if (ent == r_refdef.scene.worldentity)
12286                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12287                                         else
12288                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12289                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12290                                         R_Mesh_ColorPointer(NULL, 0, 0);
12291                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12292                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12293                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12294                                         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);
12295                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12296                                         CHECKGLERROR
12297                                 }
12298                                 if (r_shownormals.value < 0)
12299                                 {
12300                                         qglBegin(GL_LINES);
12301                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12302                                         {
12303                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12304                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12305                                                 qglVertex3f(v[0], v[1], v[2]);
12306                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12307                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12308                                                 qglVertex3f(v[0], v[1], v[2]);
12309                                         }
12310                                         qglEnd();
12311                                         CHECKGLERROR
12312                                 }
12313                                 if (r_shownormals.value > 0)
12314                                 {
12315                                         qglBegin(GL_LINES);
12316                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12317                                         {
12318                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12319                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12320                                                 qglVertex3f(v[0], v[1], v[2]);
12321                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12322                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12323                                                 qglVertex3f(v[0], v[1], v[2]);
12324                                         }
12325                                         qglEnd();
12326                                         CHECKGLERROR
12327                                         qglBegin(GL_LINES);
12328                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12329                                         {
12330                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12331                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12332                                                 qglVertex3f(v[0], v[1], v[2]);
12333                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12334                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12335                                                 qglVertex3f(v[0], v[1], v[2]);
12336                                         }
12337                                         qglEnd();
12338                                         CHECKGLERROR
12339                                         qglBegin(GL_LINES);
12340                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12341                                         {
12342                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12343                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12344                                                 qglVertex3f(v[0], v[1], v[2]);
12345                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12346                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12347                                                 qglVertex3f(v[0], v[1], v[2]);
12348                                         }
12349                                         qglEnd();
12350                                         CHECKGLERROR
12351                                 }
12352                         }
12353                 }
12354                 rsurface.texture = NULL;
12355         }
12356 }
12357
12358 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12359 int r_maxsurfacelist = 0;
12360 const msurface_t **r_surfacelist = NULL;
12361 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12362 {
12363         int i, j, endj, flagsmask;
12364         dp_model_t *model = r_refdef.scene.worldmodel;
12365         msurface_t *surfaces;
12366         unsigned char *update;
12367         int numsurfacelist = 0;
12368         if (model == NULL)
12369                 return;
12370
12371         if (r_maxsurfacelist < model->num_surfaces)
12372         {
12373                 r_maxsurfacelist = model->num_surfaces;
12374                 if (r_surfacelist)
12375                         Mem_Free((msurface_t**)r_surfacelist);
12376                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12377         }
12378
12379         RSurf_ActiveWorldEntity();
12380
12381         surfaces = model->data_surfaces;
12382         update = model->brushq1.lightmapupdateflags;
12383
12384         // update light styles on this submodel
12385         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12386         {
12387                 model_brush_lightstyleinfo_t *style;
12388                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12389                 {
12390                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12391                         {
12392                                 int *list = style->surfacelist;
12393                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12394                                 for (j = 0;j < style->numsurfaces;j++)
12395                                         update[list[j]] = true;
12396                         }
12397                 }
12398         }
12399
12400         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12401
12402         if (debug)
12403         {
12404                 R_DrawDebugModel();
12405                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12406                 return;
12407         }
12408
12409         rsurface.uselightmaptexture = false;
12410         rsurface.texture = NULL;
12411         rsurface.rtlight = NULL;
12412         numsurfacelist = 0;
12413         // add visible surfaces to draw list
12414         for (i = 0;i < model->nummodelsurfaces;i++)
12415         {
12416                 j = model->sortedmodelsurfaces[i];
12417                 if (r_refdef.viewcache.world_surfacevisible[j])
12418                         r_surfacelist[numsurfacelist++] = surfaces + j;
12419         }
12420         // update lightmaps if needed
12421         if (model->brushq1.firstrender)
12422         {
12423                 model->brushq1.firstrender = false;
12424                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12425                         if (update[j])
12426                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12427         }
12428         else if (update)
12429         {
12430                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12431                         if (r_refdef.viewcache.world_surfacevisible[j])
12432                                 if (update[j])
12433                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12434         }
12435         // don't do anything if there were no surfaces
12436         if (!numsurfacelist)
12437         {
12438                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12439                 return;
12440         }
12441         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12442         GL_AlphaTest(false);
12443
12444         // add to stats if desired
12445         if (r_speeds.integer && !skysurfaces && !depthonly)
12446         {
12447                 r_refdef.stats.world_surfaces += numsurfacelist;
12448                 for (j = 0;j < numsurfacelist;j++)
12449                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12450         }
12451
12452         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12453 }
12454
12455 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12456 {
12457         int i, j, endj, flagsmask;
12458         dp_model_t *model = ent->model;
12459         msurface_t *surfaces;
12460         unsigned char *update;
12461         int numsurfacelist = 0;
12462         if (model == NULL)
12463                 return;
12464
12465         if (r_maxsurfacelist < model->num_surfaces)
12466         {
12467                 r_maxsurfacelist = model->num_surfaces;
12468                 if (r_surfacelist)
12469                         Mem_Free((msurface_t **)r_surfacelist);
12470                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12471         }
12472
12473         // if the model is static it doesn't matter what value we give for
12474         // wantnormals and wanttangents, so this logic uses only rules applicable
12475         // to a model, knowing that they are meaningless otherwise
12476         if (ent == r_refdef.scene.worldentity)
12477                 RSurf_ActiveWorldEntity();
12478         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12479                 RSurf_ActiveModelEntity(ent, false, false, false);
12480         else if (prepass)
12481                 RSurf_ActiveModelEntity(ent, true, true, true);
12482         else if (depthonly)
12483         {
12484                 switch (vid.renderpath)
12485                 {
12486                 case RENDERPATH_GL20:
12487                 case RENDERPATH_CGGL:
12488                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12489                         break;
12490                 case RENDERPATH_GL13:
12491                 case RENDERPATH_GL11:
12492                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12493                         break;
12494                 }
12495         }
12496         else
12497         {
12498                 switch (vid.renderpath)
12499                 {
12500                 case RENDERPATH_GL20:
12501                 case RENDERPATH_CGGL:
12502                         RSurf_ActiveModelEntity(ent, true, true, false);
12503                         break;
12504                 case RENDERPATH_GL13:
12505                 case RENDERPATH_GL11:
12506                         RSurf_ActiveModelEntity(ent, true, false, false);
12507                         break;
12508                 }
12509         }
12510
12511         surfaces = model->data_surfaces;
12512         update = model->brushq1.lightmapupdateflags;
12513
12514         // update light styles
12515         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12516         {
12517                 model_brush_lightstyleinfo_t *style;
12518                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12519                 {
12520                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12521                         {
12522                                 int *list = style->surfacelist;
12523                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12524                                 for (j = 0;j < style->numsurfaces;j++)
12525                                         update[list[j]] = true;
12526                         }
12527                 }
12528         }
12529
12530         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12531
12532         if (debug)
12533         {
12534                 R_DrawDebugModel();
12535                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12536                 return;
12537         }
12538
12539         rsurface.uselightmaptexture = false;
12540         rsurface.texture = NULL;
12541         rsurface.rtlight = NULL;
12542         numsurfacelist = 0;
12543         // add visible surfaces to draw list
12544         for (i = 0;i < model->nummodelsurfaces;i++)
12545                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12546         // don't do anything if there were no surfaces
12547         if (!numsurfacelist)
12548         {
12549                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12550                 return;
12551         }
12552         // update lightmaps if needed
12553         if (update)
12554         {
12555                 int updated = 0;
12556                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12557                 {
12558                         if (update[j])
12559                         {
12560                                 updated++;
12561                                 R_BuildLightMap(ent, surfaces + j);
12562                         }
12563                 }
12564         }
12565         if (update)
12566                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12567                         if (update[j])
12568                                 R_BuildLightMap(ent, surfaces + j);
12569         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12570         GL_AlphaTest(false);
12571
12572         // add to stats if desired
12573         if (r_speeds.integer && !skysurfaces && !depthonly)
12574         {
12575                 r_refdef.stats.entities_surfaces += numsurfacelist;
12576                 for (j = 0;j < numsurfacelist;j++)
12577                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12578         }
12579
12580         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12581 }
12582
12583 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12584 {
12585         static texture_t texture;
12586         static msurface_t surface;
12587         const msurface_t *surfacelist = &surface;
12588
12589         // fake enough texture and surface state to render this geometry
12590
12591         texture.update_lastrenderframe = -1; // regenerate this texture
12592         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12593         texture.currentskinframe = skinframe;
12594         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12595         texture.offsetmapping = OFFSETMAPPING_OFF;
12596         texture.offsetscale = 1;
12597         texture.specularscalemod = 1;
12598         texture.specularpowermod = 1;
12599
12600         surface.texture = &texture;
12601         surface.num_triangles = numtriangles;
12602         surface.num_firsttriangle = firsttriangle;
12603         surface.num_vertices = numvertices;
12604         surface.num_firstvertex = firstvertex;
12605
12606         // now render it
12607         rsurface.texture = R_GetCurrentTexture(surface.texture);
12608         rsurface.uselightmaptexture = false;
12609         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12610 }
12611
12612 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)
12613 {
12614         static msurface_t surface;
12615         const msurface_t *surfacelist = &surface;
12616
12617         // fake enough texture and surface state to render this geometry
12618
12619         surface.texture = texture;
12620         surface.num_triangles = numtriangles;
12621         surface.num_firsttriangle = firsttriangle;
12622         surface.num_vertices = numvertices;
12623         surface.num_firstvertex = firstvertex;
12624
12625         // now render it
12626         rsurface.texture = R_GetCurrentTexture(surface.texture);
12627         rsurface.uselightmaptexture = false;
12628         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12629 }