]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
sort particles by effect origin rather than particle origin, this
[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_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
96 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"};
97 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"};
98 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
100 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
101 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
102 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"};
103
104 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
105 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
106 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
107 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
108 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
109 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
110 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
111 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
112
113 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)"};
114 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"};
115
116 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
117 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
120 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
121
122 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
123 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
124 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
125
126 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)"};
127 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
128 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
129 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
130 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
131 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)"};
132 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)"};
133 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)"};
134 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)"};
135
136 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)"};
137 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
138 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"};
139 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
140 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
141
142 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
143 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
144 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
145 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
146
147 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
148 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
149 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
150 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
151 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
152 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
153 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
154
155 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
156 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
157 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
158 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)"};
159
160 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"};
161
162 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"};
163
164 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
165
166 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
167 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
168 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"};
169 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
170 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
171 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
172 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
173 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)"};
174
175 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
176
177 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)"};
178
179 extern cvar_t v_glslgamma;
180
181 extern qboolean v_flipped_state;
182
183 static struct r_bloomstate_s
184 {
185         qboolean enabled;
186         qboolean hdr;
187
188         int bloomwidth, bloomheight;
189
190         int screentexturewidth, screentextureheight;
191         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
192
193         int bloomtexturewidth, bloomtextureheight;
194         rtexture_t *texture_bloom;
195
196         // arrays for rendering the screen passes
197         float screentexcoord2f[8];
198         float bloomtexcoord2f[8];
199         float offsettexcoord2f[8];
200
201         r_viewport_t viewport;
202 }
203 r_bloomstate;
204
205 r_waterstate_t r_waterstate;
206
207 /// shadow volume bsp struct with automatically growing nodes buffer
208 svbsp_t r_svbsp;
209
210 rtexture_t *r_texture_blanknormalmap;
211 rtexture_t *r_texture_white;
212 rtexture_t *r_texture_grey128;
213 rtexture_t *r_texture_black;
214 rtexture_t *r_texture_notexture;
215 rtexture_t *r_texture_whitecube;
216 rtexture_t *r_texture_normalizationcube;
217 rtexture_t *r_texture_fogattenuation;
218 rtexture_t *r_texture_gammaramps;
219 unsigned int r_texture_gammaramps_serial;
220 //rtexture_t *r_texture_fogintensity;
221 rtexture_t *r_texture_reflectcube;
222
223 // TODO: hash lookups?
224 typedef struct cubemapinfo_s
225 {
226         char basename[64];
227         rtexture_t *texture;
228 }
229 cubemapinfo_t;
230
231 int r_texture_numcubemaps;
232 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
233
234 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
235 unsigned int r_numqueries;
236 unsigned int r_maxqueries;
237
238 typedef struct r_qwskincache_s
239 {
240         char name[MAX_QPATH];
241         skinframe_t *skinframe;
242 }
243 r_qwskincache_t;
244
245 static r_qwskincache_t *r_qwskincache;
246 static int r_qwskincache_size;
247
248 /// vertex coordinates for a quad that covers the screen exactly
249 const float r_screenvertex3f[12] =
250 {
251         0, 0, 0,
252         1, 0, 0,
253         1, 1, 0,
254         0, 1, 0
255 };
256
257 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
258 {
259         int i;
260         for (i = 0;i < verts;i++)
261         {
262                 out[0] = in[0] * r;
263                 out[1] = in[1] * g;
264                 out[2] = in[2] * b;
265                 out[3] = in[3];
266                 in += 4;
267                 out += 4;
268         }
269 }
270
271 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
272 {
273         int i;
274         for (i = 0;i < verts;i++)
275         {
276                 out[0] = r;
277                 out[1] = g;
278                 out[2] = b;
279                 out[3] = a;
280                 out += 4;
281         }
282 }
283
284 // FIXME: move this to client?
285 void FOG_clear(void)
286 {
287         if (gamemode == GAME_NEHAHRA)
288         {
289                 Cvar_Set("gl_fogenable", "0");
290                 Cvar_Set("gl_fogdensity", "0.2");
291                 Cvar_Set("gl_fogred", "0.3");
292                 Cvar_Set("gl_foggreen", "0.3");
293                 Cvar_Set("gl_fogblue", "0.3");
294         }
295         r_refdef.fog_density = 0;
296         r_refdef.fog_red = 0;
297         r_refdef.fog_green = 0;
298         r_refdef.fog_blue = 0;
299         r_refdef.fog_alpha = 1;
300         r_refdef.fog_start = 0;
301         r_refdef.fog_end = 16384;
302         r_refdef.fog_height = 1<<30;
303         r_refdef.fog_fadedepth = 128;
304 }
305
306 static void R_BuildBlankTextures(void)
307 {
308         unsigned char data[4];
309         data[2] = 128; // normal X
310         data[1] = 128; // normal Y
311         data[0] = 255; // normal Z
312         data[3] = 128; // height
313         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
314         data[0] = 255;
315         data[1] = 255;
316         data[2] = 255;
317         data[3] = 255;
318         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319         data[0] = 128;
320         data[1] = 128;
321         data[2] = 128;
322         data[3] = 255;
323         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324         data[0] = 0;
325         data[1] = 0;
326         data[2] = 0;
327         data[3] = 255;
328         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329 }
330
331 static void R_BuildNoTexture(void)
332 {
333         int x, y;
334         unsigned char pix[16][16][4];
335         // this makes a light grey/dark grey checkerboard texture
336         for (y = 0;y < 16;y++)
337         {
338                 for (x = 0;x < 16;x++)
339                 {
340                         if ((y < 8) ^ (x < 8))
341                         {
342                                 pix[y][x][0] = 128;
343                                 pix[y][x][1] = 128;
344                                 pix[y][x][2] = 128;
345                                 pix[y][x][3] = 255;
346                         }
347                         else
348                         {
349                                 pix[y][x][0] = 64;
350                                 pix[y][x][1] = 64;
351                                 pix[y][x][2] = 64;
352                                 pix[y][x][3] = 255;
353                         }
354                 }
355         }
356         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
357 }
358
359 static void R_BuildWhiteCube(void)
360 {
361         unsigned char data[6*1*1*4];
362         memset(data, 255, sizeof(data));
363         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
364 }
365
366 static void R_BuildNormalizationCube(void)
367 {
368         int x, y, side;
369         vec3_t v;
370         vec_t s, t, intensity;
371 #define NORMSIZE 64
372         unsigned char *data;
373         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
374         for (side = 0;side < 6;side++)
375         {
376                 for (y = 0;y < NORMSIZE;y++)
377                 {
378                         for (x = 0;x < NORMSIZE;x++)
379                         {
380                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
382                                 switch(side)
383                                 {
384                                 default:
385                                 case 0:
386                                         v[0] = 1;
387                                         v[1] = -t;
388                                         v[2] = -s;
389                                         break;
390                                 case 1:
391                                         v[0] = -1;
392                                         v[1] = -t;
393                                         v[2] = s;
394                                         break;
395                                 case 2:
396                                         v[0] = s;
397                                         v[1] = 1;
398                                         v[2] = t;
399                                         break;
400                                 case 3:
401                                         v[0] = s;
402                                         v[1] = -1;
403                                         v[2] = -t;
404                                         break;
405                                 case 4:
406                                         v[0] = s;
407                                         v[1] = -t;
408                                         v[2] = 1;
409                                         break;
410                                 case 5:
411                                         v[0] = -s;
412                                         v[1] = -t;
413                                         v[2] = -1;
414                                         break;
415                                 }
416                                 intensity = 127.0f / sqrt(DotProduct(v, v));
417                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
418                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
419                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
420                                 data[((side*64+y)*64+x)*4+3] = 255;
421                         }
422                 }
423         }
424         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
425         Mem_Free(data);
426 }
427
428 static void R_BuildFogTexture(void)
429 {
430         int x, b;
431 #define FOGWIDTH 256
432         unsigned char data1[FOGWIDTH][4];
433         //unsigned char data2[FOGWIDTH][4];
434         double d, r, alpha;
435
436         r_refdef.fogmasktable_start = r_refdef.fog_start;
437         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
438         r_refdef.fogmasktable_range = r_refdef.fogrange;
439         r_refdef.fogmasktable_density = r_refdef.fog_density;
440
441         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
442         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
443         {
444                 d = (x * r - r_refdef.fogmasktable_start);
445                 if(developer_extra.integer)
446                         Con_DPrintf("%f ", d);
447                 d = max(0, d);
448                 if (r_fog_exp2.integer)
449                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
450                 else
451                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
452                 if(developer_extra.integer)
453                         Con_DPrintf(" : %f ", alpha);
454                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
455                 if(developer_extra.integer)
456                         Con_DPrintf(" = %f\n", alpha);
457                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
458         }
459
460         for (x = 0;x < FOGWIDTH;x++)
461         {
462                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
463                 data1[x][0] = b;
464                 data1[x][1] = b;
465                 data1[x][2] = b;
466                 data1[x][3] = 255;
467                 //data2[x][0] = 255 - b;
468                 //data2[x][1] = 255 - b;
469                 //data2[x][2] = 255 - b;
470                 //data2[x][3] = 255;
471         }
472         if (r_texture_fogattenuation)
473         {
474                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
475                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
476         }
477         else
478         {
479                 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);
480                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
481         }
482 }
483
484 //=======================================================================================================================================================
485
486 static const char *builtinshaderstring =
487 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
488 "// written by Forest 'LordHavoc' Hale\n"
489 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
490 "\n"
491 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
492 "# define USEFOG\n"
493 "#endif\n"
494 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
495 "#define USELIGHTMAP\n"
496 "#endif\n"
497 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
498 "#define USEEYEVECTOR\n"
499 "#endif\n"
500 "\n"
501 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
502 "# extension GL_ARB_texture_rectangle : enable\n"
503 "#endif\n"
504 "\n"
505 "#ifdef USESHADOWMAP2D\n"
506 "# ifdef GL_EXT_gpu_shader4\n"
507 "#   extension GL_EXT_gpu_shader4 : enable\n"
508 "# endif\n"
509 "# ifdef GL_ARB_texture_gather\n"
510 "#   extension GL_ARB_texture_gather : enable\n"
511 "# else\n"
512 "#   ifdef GL_AMD_texture_texture4\n"
513 "#     extension GL_AMD_texture_texture4 : enable\n"
514 "#   endif\n"
515 "# endif\n"
516 "#endif\n"
517 "\n"
518 "#ifdef USESHADOWMAPCUBE\n"
519 "# extension GL_EXT_gpu_shader4 : enable\n"
520 "#endif\n"
521 "\n"
522 "//#ifdef USESHADOWSAMPLER\n"
523 "//# extension GL_ARB_shadow : enable\n"
524 "//#endif\n"
525 "\n"
526 "//#ifdef __GLSL_CG_DATA_TYPES\n"
527 "//# define myhalf half\n"
528 "//# define myhalf2 half2\n"
529 "//# define myhalf3 half3\n"
530 "//# define myhalf4 half4\n"
531 "//#else\n"
532 "# define myhalf float\n"
533 "# define myhalf2 vec2\n"
534 "# define myhalf3 vec3\n"
535 "# define myhalf4 vec4\n"
536 "//#endif\n"
537 "\n"
538 "#ifdef VERTEX_SHADER\n"
539 "uniform mat4 ModelViewProjectionMatrix;\n"
540 "#endif\n"
541 "\n"
542 "#ifdef MODE_DEPTH_OR_SHADOW\n"
543 "#ifdef VERTEX_SHADER\n"
544 "void main(void)\n"
545 "{\n"
546 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
547 "}\n"
548 "#endif\n"
549 "#else // !MODE_DEPTH_ORSHADOW\n"
550 "\n"
551 "\n"
552 "\n"
553 "\n"
554 "#ifdef MODE_SHOWDEPTH\n"
555 "#ifdef VERTEX_SHADER\n"
556 "void main(void)\n"
557 "{\n"
558 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
559 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
560 "}\n"
561 "#endif\n"
562 "\n"
563 "#ifdef FRAGMENT_SHADER\n"
564 "void main(void)\n"
565 "{\n"
566 "       gl_FragColor = gl_Color;\n"
567 "}\n"
568 "#endif\n"
569 "#else // !MODE_SHOWDEPTH\n"
570 "\n"
571 "\n"
572 "\n"
573 "\n"
574 "#ifdef MODE_POSTPROCESS\n"
575 "varying vec2 TexCoord1;\n"
576 "varying vec2 TexCoord2;\n"
577 "\n"
578 "#ifdef VERTEX_SHADER\n"
579 "void main(void)\n"
580 "{\n"
581 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
582 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
583 "#ifdef USEBLOOM\n"
584 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
585 "#endif\n"
586 "}\n"
587 "#endif\n"
588 "\n"
589 "#ifdef FRAGMENT_SHADER\n"
590 "uniform sampler2D Texture_First;\n"
591 "#ifdef USEBLOOM\n"
592 "uniform sampler2D Texture_Second;\n"
593 "#endif\n"
594 "#ifdef USEGAMMARAMPS\n"
595 "uniform sampler2D Texture_GammaRamps;\n"
596 "#endif\n"
597 "#ifdef USESATURATION\n"
598 "uniform float Saturation;\n"
599 "#endif\n"
600 "#ifdef USEVIEWTINT\n"
601 "uniform vec4 ViewTintColor;\n"
602 "#endif\n"
603 "//uncomment these if you want to use them:\n"
604 "uniform vec4 UserVec1;\n"
605 "// uniform vec4 UserVec2;\n"
606 "// uniform vec4 UserVec3;\n"
607 "// uniform vec4 UserVec4;\n"
608 "// uniform float ClientTime;\n"
609 "uniform vec2 PixelSize;\n"
610 "void main(void)\n"
611 "{\n"
612 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
613 "#ifdef USEBLOOM\n"
614 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
615 "#endif\n"
616 "#ifdef USEVIEWTINT\n"
617 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
618 "#endif\n"
619 "\n"
620 "#ifdef USEPOSTPROCESSING\n"
621 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
622 "// 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"
623 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
624 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
625 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
627 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
628 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
629 "#endif\n"
630 "\n"
631 "#ifdef USESATURATION\n"
632 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
633 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
634 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
635 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
636 "#endif\n"
637 "\n"
638 "#ifdef USEGAMMARAMPS\n"
639 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
640 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
641 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
642 "#endif\n"
643 "}\n"
644 "#endif\n"
645 "#else // !MODE_POSTPROCESS\n"
646 "\n"
647 "\n"
648 "\n"
649 "\n"
650 "#ifdef MODE_GENERIC\n"
651 "#ifdef USEDIFFUSE\n"
652 "varying vec2 TexCoord1;\n"
653 "#endif\n"
654 "#ifdef USESPECULAR\n"
655 "varying vec2 TexCoord2;\n"
656 "#endif\n"
657 "#ifdef VERTEX_SHADER\n"
658 "void main(void)\n"
659 "{\n"
660 "       gl_FrontColor = gl_Color;\n"
661 "#ifdef USEDIFFUSE\n"
662 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
663 "#endif\n"
664 "#ifdef USESPECULAR\n"
665 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
666 "#endif\n"
667 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
668 "}\n"
669 "#endif\n"
670 "\n"
671 "#ifdef FRAGMENT_SHADER\n"
672 "#ifdef USEDIFFUSE\n"
673 "uniform sampler2D Texture_First;\n"
674 "#endif\n"
675 "#ifdef USESPECULAR\n"
676 "uniform sampler2D Texture_Second;\n"
677 "#endif\n"
678 "\n"
679 "void main(void)\n"
680 "{\n"
681 "       gl_FragColor = gl_Color;\n"
682 "#ifdef USEDIFFUSE\n"
683 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
684 "#endif\n"
685 "\n"
686 "#ifdef USESPECULAR\n"
687 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
688 "# ifdef USECOLORMAPPING\n"
689 "       gl_FragColor *= tex2;\n"
690 "# endif\n"
691 "# ifdef USEGLOW\n"
692 "       gl_FragColor += tex2;\n"
693 "# endif\n"
694 "# ifdef USEVERTEXTEXTUREBLEND\n"
695 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
696 "# endif\n"
697 "#endif\n"
698 "}\n"
699 "#endif\n"
700 "#else // !MODE_GENERIC\n"
701 "\n"
702 "\n"
703 "\n"
704 "\n"
705 "#ifdef MODE_BLOOMBLUR\n"
706 "varying TexCoord;\n"
707 "#ifdef VERTEX_SHADER\n"
708 "void main(void)\n"
709 "{\n"
710 "       gl_FrontColor = gl_Color;\n"
711 "       TexCoord = gl_MultiTexCoord0.xy;\n"
712 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
713 "}\n"
714 "#endif\n"
715 "\n"
716 "#ifdef FRAGMENT_SHADER\n"
717 "uniform sampler2D Texture_First;\n"
718 "uniform vec4 BloomBlur_Parameters;\n"
719 "\n"
720 "void main(void)\n"
721 "{\n"
722 "       int i;\n"
723 "       vec2 tc = TexCoord;\n"
724 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
725 "       tc += BloomBlur_Parameters.xy;\n"
726 "       for (i = 1;i < SAMPLES;i++)\n"
727 "       {\n"
728 "               color += texture2D(Texture_First, tc).rgb;\n"
729 "               tc += BloomBlur_Parameters.xy;\n"
730 "       }\n"
731 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
732 "}\n"
733 "#endif\n"
734 "#else // !MODE_BLOOMBLUR\n"
735 "#ifdef MODE_REFRACTION\n"
736 "varying vec2 TexCoord;\n"
737 "varying vec4 ModelViewProjectionPosition;\n"
738 "uniform mat4 TexMatrix;\n"
739 "#ifdef VERTEX_SHADER\n"
740 "\n"
741 "void main(void)\n"
742 "{\n"
743 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
744 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
745 "       ModelViewProjectionPosition = gl_Position;\n"
746 "}\n"
747 "#endif\n"
748 "\n"
749 "#ifdef FRAGMENT_SHADER\n"
750 "uniform sampler2D Texture_Normal;\n"
751 "uniform sampler2D Texture_Refraction;\n"
752 "uniform sampler2D Texture_Reflection;\n"
753 "\n"
754 "uniform vec4 DistortScaleRefractReflect;\n"
755 "uniform vec4 ScreenScaleRefractReflect;\n"
756 "uniform vec4 ScreenCenterRefractReflect;\n"
757 "uniform vec4 RefractColor;\n"
758 "uniform vec4 ReflectColor;\n"
759 "uniform float ReflectFactor;\n"
760 "uniform float ReflectOffset;\n"
761 "\n"
762 "void main(void)\n"
763 "{\n"
764 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
765 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
766 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
767 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
768 "       // FIXME temporary hack to detect the case that the reflection\n"
769 "       // gets blackened at edges due to leaving the area that contains actual\n"
770 "       // content.\n"
771 "       // Remove this 'ack once we have a better way to stop this thing from\n"
772 "       // 'appening.\n"
773 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
774 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
775 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
776 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
777 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
778 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
779 "}\n"
780 "#endif\n"
781 "#else // !MODE_REFRACTION\n"
782 "\n"
783 "\n"
784 "\n"
785 "\n"
786 "#ifdef MODE_WATER\n"
787 "varying vec2 TexCoord;\n"
788 "varying vec3 EyeVector;\n"
789 "varying vec4 ModelViewProjectionPosition;\n"
790 "#ifdef VERTEX_SHADER\n"
791 "uniform vec3 EyePosition;\n"
792 "uniform mat4 TexMatrix;\n"
793 "\n"
794 "void main(void)\n"
795 "{\n"
796 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
797 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
798 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
799 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
800 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
801 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "       ModelViewProjectionPosition = gl_Position;\n"
803 "}\n"
804 "#endif\n"
805 "\n"
806 "#ifdef FRAGMENT_SHADER\n"
807 "uniform sampler2D Texture_Normal;\n"
808 "uniform sampler2D Texture_Refraction;\n"
809 "uniform sampler2D Texture_Reflection;\n"
810 "\n"
811 "uniform vec4 DistortScaleRefractReflect;\n"
812 "uniform vec4 ScreenScaleRefractReflect;\n"
813 "uniform vec4 ScreenCenterRefractReflect;\n"
814 "uniform vec4 RefractColor;\n"
815 "uniform vec4 ReflectColor;\n"
816 "uniform float ReflectFactor;\n"
817 "uniform float ReflectOffset;\n"
818 "\n"
819 "void main(void)\n"
820 "{\n"
821 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
822 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
823 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
824 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
825 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
826 "       // FIXME temporary hack to detect the case that the reflection\n"
827 "       // gets blackened at edges due to leaving the area that contains actual\n"
828 "       // content.\n"
829 "       // Remove this 'ack once we have a better way to stop this thing from\n"
830 "       // 'appening.\n"
831 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
832 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
833 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
834 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
835 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
836 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
837 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
838 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
839 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
840 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
841 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
842 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
843 "}\n"
844 "#endif\n"
845 "#else // !MODE_WATER\n"
846 "\n"
847 "\n"
848 "\n"
849 "\n"
850 "// common definitions between vertex shader and fragment shader:\n"
851 "\n"
852 "varying vec2 TexCoord;\n"
853 "#ifdef USEVERTEXTEXTUREBLEND\n"
854 "varying vec2 TexCoord2;\n"
855 "#endif\n"
856 "#ifdef USELIGHTMAP\n"
857 "varying vec2 TexCoordLightmap;\n"
858 "#endif\n"
859 "\n"
860 "#ifdef MODE_LIGHTSOURCE\n"
861 "varying vec3 CubeVector;\n"
862 "#endif\n"
863 "\n"
864 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
865 "varying vec3 LightVector;\n"
866 "#endif\n"
867 "\n"
868 "#ifdef USEEYEVECTOR\n"
869 "varying vec3 EyeVector;\n"
870 "#endif\n"
871 "#ifdef USEFOG\n"
872 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
873 "#endif\n"
874 "\n"
875 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
876 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
877 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
878 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
879 "#endif\n"
880 "\n"
881 "#ifdef USEREFLECTION\n"
882 "varying vec4 ModelViewProjectionPosition;\n"
883 "#endif\n"
884 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
885 "uniform vec3 LightPosition;\n"
886 "varying vec4 ModelViewPosition;\n"
887 "#endif\n"
888 "\n"
889 "#ifdef MODE_LIGHTSOURCE\n"
890 "uniform vec3 LightPosition;\n"
891 "#endif\n"
892 "uniform vec3 EyePosition;\n"
893 "#ifdef MODE_LIGHTDIRECTION\n"
894 "uniform vec3 LightDir;\n"
895 "#endif\n"
896 "uniform vec4 FogPlane;\n"
897 "\n"
898 "#ifdef USESHADOWMAPORTHO\n"
899 "varying vec3 ShadowMapTC;\n"
900 "#endif\n"
901 "\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "// 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"
907 "\n"
908 "// fragment shader specific:\n"
909 "#ifdef FRAGMENT_SHADER\n"
910 "\n"
911 "uniform sampler2D Texture_Normal;\n"
912 "uniform sampler2D Texture_Color;\n"
913 "uniform sampler2D Texture_Gloss;\n"
914 "#ifdef USEGLOW\n"
915 "uniform sampler2D Texture_Glow;\n"
916 "#endif\n"
917 "#ifdef USEVERTEXTEXTUREBLEND\n"
918 "uniform sampler2D Texture_SecondaryNormal;\n"
919 "uniform sampler2D Texture_SecondaryColor;\n"
920 "uniform sampler2D Texture_SecondaryGloss;\n"
921 "#ifdef USEGLOW\n"
922 "uniform sampler2D Texture_SecondaryGlow;\n"
923 "#endif\n"
924 "#endif\n"
925 "#ifdef USECOLORMAPPING\n"
926 "uniform sampler2D Texture_Pants;\n"
927 "uniform sampler2D Texture_Shirt;\n"
928 "#endif\n"
929 "#ifdef USEFOG\n"
930 "uniform sampler2D Texture_FogMask;\n"
931 "#endif\n"
932 "#ifdef USELIGHTMAP\n"
933 "uniform sampler2D Texture_Lightmap;\n"
934 "#endif\n"
935 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
936 "uniform sampler2D Texture_Deluxemap;\n"
937 "#endif\n"
938 "#ifdef USEREFLECTION\n"
939 "uniform sampler2D Texture_Reflection;\n"
940 "#endif\n"
941 "\n"
942 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
943 "uniform sampler2D Texture_ScreenDepth;\n"
944 "uniform sampler2D Texture_ScreenNormalMap;\n"
945 "#endif\n"
946 "#ifdef USEDEFERREDLIGHTMAP\n"
947 "uniform sampler2D Texture_ScreenDiffuse;\n"
948 "uniform sampler2D Texture_ScreenSpecular;\n"
949 "#endif\n"
950 "\n"
951 "uniform myhalf3 Color_Pants;\n"
952 "uniform myhalf3 Color_Shirt;\n"
953 "uniform myhalf3 FogColor;\n"
954 "\n"
955 "#ifdef USEFOG\n"
956 "uniform float FogRangeRecip;\n"
957 "uniform float FogPlaneViewDist;\n"
958 "uniform float FogHeightFade;\n"
959 "float FogVertex(void)\n"
960 "{\n"
961 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
962 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
963 "       float fogfrac;\n"
964 "#ifdef USEFOGOUTSIDE\n"
965 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
966 "#else\n"
967 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
968 "#endif\n"
969 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
970 "}\n"
971 "#endif\n"
972 "\n"
973 "#ifdef USEOFFSETMAPPING\n"
974 "uniform float OffsetMapping_Scale;\n"
975 "vec2 OffsetMapping(vec2 TexCoord)\n"
976 "{\n"
977 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
978 "       // 14 sample relief mapping: linear search and then binary search\n"
979 "       // this basically steps forward a small amount repeatedly until it finds\n"
980 "       // itself inside solid, then jitters forward and back using decreasing\n"
981 "       // amounts to find the impact\n"
982 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
983 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
984 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
985 "       vec3 RT = vec3(TexCoord, 1);\n"
986 "       OffsetVector *= 0.1;\n"
987 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
988 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
989 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
990 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
991 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
992 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
993 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
994 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
995 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
996 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
997 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
998 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1000 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1001 "       return RT.xy;\n"
1002 "#else\n"
1003 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1004 "       // this basically moves forward the full distance, and then backs up based\n"
1005 "       // on height of samples\n"
1006 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1007 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1008 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1009 "       TexCoord += OffsetVector;\n"
1010 "       OffsetVector *= 0.333;\n"
1011 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1012 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1014 "       return TexCoord;\n"
1015 "#endif\n"
1016 "}\n"
1017 "#endif // USEOFFSETMAPPING\n"
1018 "\n"
1019 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1020 "uniform sampler2D Texture_Attenuation;\n"
1021 "uniform samplerCube Texture_Cube;\n"
1022 "#endif\n"
1023 "\n"
1024 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1025 "\n"
1026 "#ifdef USESHADOWMAPRECT\n"
1027 "# ifdef USESHADOWSAMPLER\n"
1028 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1029 "# else\n"
1030 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1031 "# endif\n"
1032 "#endif\n"
1033 "\n"
1034 "#ifdef USESHADOWMAP2D\n"
1035 "# ifdef USESHADOWSAMPLER\n"
1036 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1037 "# else\n"
1038 "uniform sampler2D Texture_ShadowMap2D;\n"
1039 "# endif\n"
1040 "#endif\n"
1041 "\n"
1042 "#ifdef USESHADOWMAPVSDCT\n"
1043 "uniform samplerCube Texture_CubeProjection;\n"
1044 "#endif\n"
1045 "\n"
1046 "#ifdef USESHADOWMAPCUBE\n"
1047 "# ifdef USESHADOWSAMPLER\n"
1048 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1049 "# else\n"
1050 "uniform samplerCube Texture_ShadowMapCube;\n"
1051 "# endif\n"
1052 "#endif\n"
1053 "\n"
1054 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1055 "uniform vec2 ShadowMap_TextureScale;\n"
1056 "uniform vec4 ShadowMap_Parameters;\n"
1057 "#endif\n"
1058 "\n"
1059 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1060 "# ifdef USESHADOWMAPORTHO\n"
1061 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1062 "# else\n"
1063 "#  ifdef USESHADOWMAPVSDCT\n"
1064 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1065 "{\n"
1066 "       vec3 adir = abs(dir);\n"
1067 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1068 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1069 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1070 "}\n"
1071 "#  else\n"
1072 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1073 "{\n"
1074 "       vec3 adir = abs(dir);\n"
1075 "       float ma = adir.z;\n"
1076 "       vec4 proj = vec4(dir, 2.5);\n"
1077 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1078 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1079 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1080 "       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"
1081 "}\n"
1082 "#  endif\n"
1083 "# endif\n"
1084 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1085 "\n"
1086 "#ifdef USESHADOWMAPCUBE\n"
1087 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1088 "{\n"
1089 "       vec3 adir = abs(dir);\n"
1090 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1091 "}\n"
1092 "#endif\n"
1093 "\n"
1094 "# ifdef USESHADOWMAPRECT\n"
1095 "float ShadowMapCompare(vec3 dir)\n"
1096 "{\n"
1097 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1098 "       float f;\n"
1099 "#  ifdef USESHADOWSAMPLER\n"
1100 "\n"
1101 "#    ifdef USESHADOWMAPPCF\n"
1102 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1103 "       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"
1104 "#    else\n"
1105 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1106 "#    endif\n"
1107 "\n"
1108 "#  else\n"
1109 "\n"
1110 "#    ifdef USESHADOWMAPPCF\n"
1111 "#      if USESHADOWMAPPCF > 1\n"
1112 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1113 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1114 "       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"
1115 "       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"
1116 "       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"
1117 "       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"
1118 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1119 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1120 "#      else\n"
1121 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1122 "       vec2 offset = fract(shadowmaptc.xy);\n"
1123 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1124 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1125 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1126 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1127 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1128 "#      endif\n"
1129 "#    else\n"
1130 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1131 "#    endif\n"
1132 "\n"
1133 "#  endif\n"
1134 "#  ifdef USESHADOWMAPORTHO\n"
1135 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1136 "#  else\n"
1137 "       return f;\n"
1138 "#  endif\n"
1139 "}\n"
1140 "# endif\n"
1141 "\n"
1142 "# ifdef USESHADOWMAP2D\n"
1143 "float ShadowMapCompare(vec3 dir)\n"
1144 "{\n"
1145 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1146 "       float f;\n"
1147 "\n"
1148 "#  ifdef USESHADOWSAMPLER\n"
1149 "#    ifdef USESHADOWMAPPCF\n"
1150 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1151 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1152 "       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"
1153 "#    else\n"
1154 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1155 "#    endif\n"
1156 "#  else\n"
1157 "#    ifdef USESHADOWMAPPCF\n"
1158 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1159 "#      ifdef GL_ARB_texture_gather\n"
1160 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1161 "#      else\n"
1162 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1163 "#      endif\n"
1164 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1165 "       center *= ShadowMap_TextureScale;\n"
1166 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1167 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1168 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1169 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1170 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1171 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1172 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1173 "#     else\n"
1174 "#      ifdef GL_EXT_gpu_shader4\n"
1175 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1176 "#      else\n"
1177 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1178 "#      endif\n"
1179 "#      if USESHADOWMAPPCF > 1\n"
1180 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1181 "       center *= ShadowMap_TextureScale;\n"
1182 "       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"
1183 "       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"
1184 "       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"
1185 "       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"
1186 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1187 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1188 "#      else\n"
1189 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1190 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1191 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1192 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1193 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1194 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1195 "#      endif\n"
1196 "#     endif\n"
1197 "#    else\n"
1198 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1199 "#    endif\n"
1200 "#  endif\n"
1201 "#  ifdef USESHADOWMAPORTHO\n"
1202 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1203 "#  else\n"
1204 "       return f;\n"
1205 "#  endif\n"
1206 "}\n"
1207 "# endif\n"
1208 "\n"
1209 "# ifdef USESHADOWMAPCUBE\n"
1210 "float ShadowMapCompare(vec3 dir)\n"
1211 "{\n"
1212 "       // apply depth texture cubemap as light filter\n"
1213 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1214 "       float f;\n"
1215 "#  ifdef USESHADOWSAMPLER\n"
1216 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1217 "#  else\n"
1218 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1219 "#  endif\n"
1220 "       return f;\n"
1221 "}\n"
1222 "# endif\n"
1223 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1224 "#endif // FRAGMENT_SHADER\n"
1225 "\n"
1226 "\n"
1227 "\n"
1228 "\n"
1229 "#ifdef MODE_DEFERREDGEOMETRY\n"
1230 "#ifdef VERTEX_SHADER\n"
1231 "uniform mat4 TexMatrix;\n"
1232 "#ifdef USEVERTEXTEXTUREBLEND\n"
1233 "uniform mat4 BackgroundTexMatrix;\n"
1234 "#endif\n"
1235 "uniform mat4 ModelViewMatrix;\n"
1236 "void main(void)\n"
1237 "{\n"
1238 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1239 "#ifdef USEVERTEXTEXTUREBLEND\n"
1240 "       gl_FrontColor = gl_Color;\n"
1241 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1242 "#endif\n"
1243 "\n"
1244 "       // transform unnormalized eye direction into tangent space\n"
1245 "#ifdef USEOFFSETMAPPING\n"
1246 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1247 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1248 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1249 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1250 "#endif\n"
1251 "\n"
1252 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1253 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1254 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1255 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1256 "}\n"
1257 "#endif // VERTEX_SHADER\n"
1258 "\n"
1259 "#ifdef FRAGMENT_SHADER\n"
1260 "void main(void)\n"
1261 "{\n"
1262 "#ifdef USEOFFSETMAPPING\n"
1263 "       // apply offsetmapping\n"
1264 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1265 "#define TexCoord TexCoordOffset\n"
1266 "#endif\n"
1267 "\n"
1268 "#ifdef USEALPHAKILL\n"
1269 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1270 "               discard;\n"
1271 "#endif\n"
1272 "\n"
1273 "#ifdef USEVERTEXTEXTUREBLEND\n"
1274 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1275 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1276 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1277 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1278 "#endif\n"
1279 "\n"
1280 "#ifdef USEVERTEXTEXTUREBLEND\n"
1281 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1282 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1283 "#else\n"
1284 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1285 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1286 "#endif\n"
1287 "\n"
1288 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1289 "}\n"
1290 "#endif // FRAGMENT_SHADER\n"
1291 "#else // !MODE_DEFERREDGEOMETRY\n"
1292 "\n"
1293 "\n"
1294 "\n"
1295 "\n"
1296 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1297 "#ifdef VERTEX_SHADER\n"
1298 "uniform mat4 ModelViewMatrix;\n"
1299 "void main(void)\n"
1300 "{\n"
1301 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1302 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1303 "}\n"
1304 "#endif // VERTEX_SHADER\n"
1305 "\n"
1306 "#ifdef FRAGMENT_SHADER\n"
1307 "uniform mat4 ViewToLight;\n"
1308 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1309 "uniform vec2 ScreenToDepth;\n"
1310 "uniform myhalf3 DeferredColor_Ambient;\n"
1311 "uniform myhalf3 DeferredColor_Diffuse;\n"
1312 "#ifdef USESPECULAR\n"
1313 "uniform myhalf3 DeferredColor_Specular;\n"
1314 "uniform myhalf SpecularPower;\n"
1315 "#endif\n"
1316 "uniform myhalf2 PixelToScreenTexCoord;\n"
1317 "void main(void)\n"
1318 "{\n"
1319 "       // calculate viewspace pixel position\n"
1320 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1321 "       vec3 position;\n"
1322 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1323 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1324 "       // decode viewspace pixel normal\n"
1325 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1326 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1327 "       // surfacenormal = pixel normal in viewspace\n"
1328 "       // LightVector = pixel to light in viewspace\n"
1329 "       // CubeVector = position in lightspace\n"
1330 "       // eyevector = pixel to view in viewspace\n"
1331 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1332 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1333 "#ifdef USEDIFFUSE\n"
1334 "       // calculate diffuse shading\n"
1335 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1336 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1337 "#endif\n"
1338 "#ifdef USESPECULAR\n"
1339 "       // calculate directional shading\n"
1340 "       vec3 eyevector = position * -1.0;\n"
1341 "#  ifdef USEEXACTSPECULARMATH\n"
1342 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1343 "#  else\n"
1344 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1345 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1346 "#  endif\n"
1347 "#endif\n"
1348 "\n"
1349 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1350 "       fade *= ShadowMapCompare(CubeVector);\n"
1351 "#endif\n"
1352 "\n"
1353 "#ifdef USEDIFFUSE\n"
1354 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1355 "#else\n"
1356 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1357 "#endif\n"
1358 "#ifdef USESPECULAR\n"
1359 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1360 "#else\n"
1361 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1362 "#endif\n"
1363 "\n"
1364 "# ifdef USECUBEFILTER\n"
1365 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1366 "       gl_FragData[0].rgb *= cubecolor;\n"
1367 "       gl_FragData[1].rgb *= cubecolor;\n"
1368 "# endif\n"
1369 "}\n"
1370 "#endif // FRAGMENT_SHADER\n"
1371 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1372 "\n"
1373 "\n"
1374 "\n"
1375 "\n"
1376 "#ifdef VERTEX_SHADER\n"
1377 "uniform mat4 TexMatrix;\n"
1378 "#ifdef USEVERTEXTEXTUREBLEND\n"
1379 "uniform mat4 BackgroundTexMatrix;\n"
1380 "#endif\n"
1381 "#ifdef MODE_LIGHTSOURCE\n"
1382 "uniform mat4 ModelToLight;\n"
1383 "#endif\n"
1384 "#ifdef USESHADOWMAPORTHO\n"
1385 "uniform mat4 ShadowMapMatrix;\n"
1386 "#endif\n"
1387 "void main(void)\n"
1388 "{\n"
1389 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "#endif\n"
1392 "       // copy the surface texcoord\n"
1393 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1394 "#ifdef USEVERTEXTEXTUREBLEND\n"
1395 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1396 "#endif\n"
1397 "#ifdef USELIGHTMAP\n"
1398 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1399 "#endif\n"
1400 "\n"
1401 "#ifdef MODE_LIGHTSOURCE\n"
1402 "       // transform vertex position into light attenuation/cubemap space\n"
1403 "       // (-1 to +1 across the light box)\n"
1404 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1405 "\n"
1406 "# ifdef USEDIFFUSE\n"
1407 "       // transform unnormalized light direction into tangent space\n"
1408 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1409 "       //  normalize it per pixel)\n"
1410 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1411 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1412 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1413 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1414 "# endif\n"
1415 "#endif\n"
1416 "\n"
1417 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1418 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1419 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1420 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1421 "#endif\n"
1422 "\n"
1423 "       // transform unnormalized eye direction into tangent space\n"
1424 "#ifdef USEEYEVECTOR\n"
1425 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1426 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1427 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1428 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1429 "#endif\n"
1430 "\n"
1431 "#ifdef USEFOG\n"
1432 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1433 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1434 "#endif\n"
1435 "\n"
1436 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1437 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1438 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1439 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1440 "#endif\n"
1441 "\n"
1442 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1443 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1444 "\n"
1445 "#ifdef USESHADOWMAPORTHO\n"
1446 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1447 "#endif\n"
1448 "\n"
1449 "#ifdef USEREFLECTION\n"
1450 "       ModelViewProjectionPosition = gl_Position;\n"
1451 "#endif\n"
1452 "}\n"
1453 "#endif // VERTEX_SHADER\n"
1454 "\n"
1455 "\n"
1456 "\n"
1457 "\n"
1458 "#ifdef FRAGMENT_SHADER\n"
1459 "#ifdef USEDEFERREDLIGHTMAP\n"
1460 "uniform myhalf2 PixelToScreenTexCoord;\n"
1461 "uniform myhalf3 DeferredMod_Diffuse;\n"
1462 "uniform myhalf3 DeferredMod_Specular;\n"
1463 "#endif\n"
1464 "uniform myhalf3 Color_Ambient;\n"
1465 "uniform myhalf3 Color_Diffuse;\n"
1466 "uniform myhalf3 Color_Specular;\n"
1467 "uniform myhalf SpecularPower;\n"
1468 "#ifdef USEGLOW\n"
1469 "uniform myhalf3 Color_Glow;\n"
1470 "#endif\n"
1471 "uniform myhalf Alpha;\n"
1472 "#ifdef USEREFLECTION\n"
1473 "uniform vec4 DistortScaleRefractReflect;\n"
1474 "uniform vec4 ScreenScaleRefractReflect;\n"
1475 "uniform vec4 ScreenCenterRefractReflect;\n"
1476 "uniform myhalf4 ReflectColor;\n"
1477 "#endif\n"
1478 "#ifdef USEREFLECTCUBE\n"
1479 "uniform mat4 ModelToReflectCube;\n"
1480 "uniform sampler2D Texture_ReflectMask;\n"
1481 "uniform samplerCube Texture_ReflectCube;\n"
1482 "#endif\n"
1483 "#ifdef MODE_LIGHTDIRECTION\n"
1484 "uniform myhalf3 LightColor;\n"
1485 "#endif\n"
1486 "#ifdef MODE_LIGHTSOURCE\n"
1487 "uniform myhalf3 LightColor;\n"
1488 "#endif\n"
1489 "void main(void)\n"
1490 "{\n"
1491 "#ifdef USEOFFSETMAPPING\n"
1492 "       // apply offsetmapping\n"
1493 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1494 "#define TexCoord TexCoordOffset\n"
1495 "#endif\n"
1496 "\n"
1497 "       // combine the diffuse textures (base, pants, shirt)\n"
1498 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1499 "#ifdef USEALPHAKILL\n"
1500 "       if (color.a < 0.5)\n"
1501 "               discard;\n"
1502 "#endif\n"
1503 "       color.a *= Alpha;\n"
1504 "#ifdef USECOLORMAPPING\n"
1505 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1506 "#endif\n"
1507 "#ifdef USEVERTEXTEXTUREBLEND\n"
1508 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1509 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1510 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1511 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1512 "       color.a = 1.0;\n"
1513 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1514 "#endif\n"
1515 "\n"
1516 "       // get the surface normal\n"
1517 "#ifdef USEVERTEXTEXTUREBLEND\n"
1518 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1519 "#else\n"
1520 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1521 "#endif\n"
1522 "\n"
1523 "       // get the material colors\n"
1524 "       myhalf3 diffusetex = color.rgb;\n"
1525 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1526 "# ifdef USEVERTEXTEXTUREBLEND\n"
1527 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1528 "# else\n"
1529 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1530 "# endif\n"
1531 "#endif\n"
1532 "\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1535 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1536 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1537 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1538 "#endif\n"
1539 "\n"
1540 "\n"
1541 "\n"
1542 "\n"
1543 "#ifdef MODE_LIGHTSOURCE\n"
1544 "       // light source\n"
1545 "#ifdef USEDIFFUSE\n"
1546 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1547 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1548 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1549 "#ifdef USESPECULAR\n"
1550 "#ifdef USEEXACTSPECULARMATH\n"
1551 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1552 "#else\n"
1553 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1554 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1555 "#endif\n"
1556 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1557 "#endif\n"
1558 "#else\n"
1559 "       color.rgb = diffusetex * Color_Ambient;\n"
1560 "#endif\n"
1561 "       color.rgb *= LightColor;\n"
1562 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1563 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1564 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1565 "#endif\n"
1566 "# ifdef USECUBEFILTER\n"
1567 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1568 "# endif\n"
1569 "#endif // MODE_LIGHTSOURCE\n"
1570 "\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "#define SHADING\n"
1576 "#ifdef USEDIFFUSE\n"
1577 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1578 "#endif\n"
1579 "#define lightcolor LightColor\n"
1580 "#endif // MODE_LIGHTDIRECTION\n"
1581 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1582 "#define SHADING\n"
1583 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1584 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1585 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1586 "       // convert modelspace light vector to tangentspace\n"
1587 "       myhalf3 lightnormal;\n"
1588 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1589 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1590 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1591 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1592 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1593 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1594 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1595 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1596 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1597 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1598 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1599 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1600 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1601 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1602 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1603 "#define SHADING\n"
1604 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1605 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1606 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1607 "#endif\n"
1608 "\n"
1609 "\n"
1610 "\n"
1611 "\n"
1612 "#ifdef MODE_LIGHTMAP\n"
1613 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1614 "#endif // MODE_LIGHTMAP\n"
1615 "#ifdef MODE_VERTEXCOLOR\n"
1616 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1617 "#endif // MODE_VERTEXCOLOR\n"
1618 "#ifdef MODE_FLATCOLOR\n"
1619 "       color.rgb = diffusetex * Color_Ambient;\n"
1620 "#endif // MODE_FLATCOLOR\n"
1621 "\n"
1622 "\n"
1623 "\n"
1624 "\n"
1625 "#ifdef SHADING\n"
1626 "# ifdef USEDIFFUSE\n"
1627 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1628 "#  ifdef USESPECULAR\n"
1629 "#   ifdef USEEXACTSPECULARMATH\n"
1630 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1631 "#   else\n"
1632 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1633 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1634 "#   endif\n"
1635 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1636 "#  else\n"
1637 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1638 "#  endif\n"
1639 "# else\n"
1640 "       color.rgb = diffusetex * Color_Ambient;\n"
1641 "# endif\n"
1642 "#endif\n"
1643 "\n"
1644 "#ifdef USESHADOWMAPORTHO\n"
1645 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1646 "#endif\n"
1647 "\n"
1648 "#ifdef USEDEFERREDLIGHTMAP\n"
1649 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1650 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1651 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1652 "#endif\n"
1653 "\n"
1654 "#ifdef USEGLOW\n"
1655 "#ifdef USEVERTEXTEXTUREBLEND\n"
1656 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1657 "#else\n"
1658 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1659 "#endif\n"
1660 "#endif\n"
1661 "\n"
1662 "#ifdef USEFOG\n"
1663 "#ifdef MODE_LIGHTSOURCE\n"
1664 "       color.rgb *= myhalf(FogVertex());\n"
1665 "#else\n"
1666 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1667 "#endif\n"
1668 "#endif\n"
1669 "\n"
1670 "       // 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"
1671 "#ifdef USEREFLECTION\n"
1672 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1673 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1674 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1675 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1676 "       // FIXME temporary hack to detect the case that the reflection\n"
1677 "       // gets blackened at edges due to leaving the area that contains actual\n"
1678 "       // content.\n"
1679 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1680 "       // 'appening.\n"
1681 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1682 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1683 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1684 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1685 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1686 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1687 "#endif\n"
1688 "\n"
1689 "       gl_FragColor = vec4(color);\n"
1690 "}\n"
1691 "#endif // FRAGMENT_SHADER\n"
1692 "\n"
1693 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1694 "#endif // !MODE_DEFERREDGEOMETRY\n"
1695 "#endif // !MODE_WATER\n"
1696 "#endif // !MODE_REFRACTION\n"
1697 "#endif // !MODE_BLOOMBLUR\n"
1698 "#endif // !MODE_GENERIC\n"
1699 "#endif // !MODE_POSTPROCESS\n"
1700 "#endif // !MODE_SHOWDEPTH\n"
1701 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1702 ;
1703
1704 /*
1705 =========================================================================================================================================================
1706
1707
1708
1709 =========================================================================================================================================================
1710
1711
1712
1713 =========================================================================================================================================================
1714
1715
1716
1717 =========================================================================================================================================================
1718
1719
1720
1721 =========================================================================================================================================================
1722
1723
1724
1725 =========================================================================================================================================================
1726
1727
1728
1729 =========================================================================================================================================================
1730 */
1731
1732 const char *builtincgshaderstring =
1733 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1734 "// written by Forest 'LordHavoc' Hale\n"
1735 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1736 "\n"
1737 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1738 "# define USEFOG\n"
1739 "#endif\n"
1740 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1741 "#define USELIGHTMAP\n"
1742 "#endif\n"
1743 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1744 "#define USEEYEVECTOR\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1748 "#ifdef VERTEX_SHADER\n"
1749 "void main\n"
1750 "(\n"
1751 "float4 gl_Vertex : POSITION,\n"
1752 "uniform float4x4 ModelViewProjectionMatrix,\n"
1753 "out float4 gl_Position : POSITION\n"
1754 ")\n"
1755 "{\n"
1756 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1757 "}\n"
1758 "#endif\n"
1759 "#else // !MODE_DEPTH_ORSHADOW\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "\n"
1764 "#ifdef MODE_SHOWDEPTH\n"
1765 "#ifdef VERTEX_SHADER\n"
1766 "void main\n"
1767 "(\n"
1768 "float4 gl_Vertex : POSITION,\n"
1769 "uniform float4x4 ModelViewProjectionMatrix,\n"
1770 "out float4 gl_Position : POSITION,\n"
1771 "out float4 gl_FrontColor : COLOR0\n"
1772 ")\n"
1773 "{\n"
1774 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1775 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1776 "}\n"
1777 "#endif\n"
1778 "\n"
1779 "#ifdef FRAGMENT_SHADER\n"
1780 "void main\n"
1781 "(\n"
1782 "float4 gl_FrontColor : COLOR0,\n"
1783 "out float4 gl_FragColor : COLOR\n"
1784 ")\n"
1785 "{\n"
1786 "       gl_FragColor = gl_FrontColor;\n"
1787 "}\n"
1788 "#endif\n"
1789 "#else // !MODE_SHOWDEPTH\n"
1790 "\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "#ifdef MODE_POSTPROCESS\n"
1795 "\n"
1796 "#ifdef VERTEX_SHADER\n"
1797 "void main\n"
1798 "(\n"
1799 "float4 gl_Vertex : POSITION,\n"
1800 "uniform float4x4 ModelViewProjectionMatrix,\n"
1801 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1802 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1803 "out float4 gl_Position : POSITION,\n"
1804 "out float2 TexCoord1 : TEXCOORD0,\n"
1805 "out float2 TexCoord2 : TEXCOORD1\n"
1806 ")\n"
1807 "{\n"
1808 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1809 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1810 "#ifdef USEBLOOM\n"
1811 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1812 "#endif\n"
1813 "}\n"
1814 "#endif\n"
1815 "\n"
1816 "#ifdef FRAGMENT_SHADER\n"
1817 "void main\n"
1818 "(\n"
1819 "float2 TexCoord1 : TEXCOORD0,\n"
1820 "float2 TexCoord2 : TEXCOORD1,\n"
1821 "uniform sampler2D Texture_First,\n"
1822 "#ifdef USEBLOOM\n"
1823 "uniform sampler2D Texture_Second,\n"
1824 "#endif\n"
1825 "#ifdef USEGAMMARAMPS\n"
1826 "uniform sampler2D Texture_GammaRamps,\n"
1827 "#endif\n"
1828 "#ifdef USESATURATION\n"
1829 "uniform float Saturation,\n"
1830 "#endif\n"
1831 "#ifdef USEVIEWTINT\n"
1832 "uniform float4 ViewTintColor,\n"
1833 "#endif\n"
1834 "uniform float4 UserVec1,\n"
1835 "uniform float4 UserVec2,\n"
1836 "uniform float4 UserVec3,\n"
1837 "uniform float4 UserVec4,\n"
1838 "uniform float ClientTime,\n"
1839 "uniform float2 PixelSize,\n"
1840 "out float4 gl_FragColor : COLOR\n"
1841 ")\n"
1842 "{\n"
1843 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1844 "#ifdef USEBLOOM\n"
1845 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1846 "#endif\n"
1847 "#ifdef USEVIEWTINT\n"
1848 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1849 "#endif\n"
1850 "\n"
1851 "#ifdef USEPOSTPROCESSING\n"
1852 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1853 "// 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"
1854 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1855 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1856 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1857 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1858 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1859 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef USESATURATION\n"
1863 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1864 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1865 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1866 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1867 "#endif\n"
1868 "\n"
1869 "#ifdef USEGAMMARAMPS\n"
1870 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1871 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1872 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1873 "#endif\n"
1874 "}\n"
1875 "#endif\n"
1876 "#else // !MODE_POSTPROCESS\n"
1877 "\n"
1878 "\n"
1879 "\n"
1880 "\n"
1881 "#ifdef MODE_GENERIC\n"
1882 "#ifdef VERTEX_SHADER\n"
1883 "void main\n"
1884 "(\n"
1885 "float4 gl_Vertex : POSITION,\n"
1886 "uniform float4x4 ModelViewProjectionMatrix,\n"
1887 "float4 gl_Color : COLOR0,\n"
1888 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1889 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1890 "out float4 gl_Position : POSITION,\n"
1891 "out float4 gl_FrontColor : COLOR,\n"
1892 "out float2 TexCoord1 : TEXCOORD0,\n"
1893 "out float2 TexCoord2 : TEXCOORD1\n"
1894 ")\n"
1895 "{\n"
1896 "       gl_FrontColor = gl_Color;\n"
1897 "#ifdef USEDIFFUSE\n"
1898 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1899 "#endif\n"
1900 "#ifdef USESPECULAR\n"
1901 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1902 "#endif\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "}\n"
1905 "#endif\n"
1906 "\n"
1907 "#ifdef FRAGMENT_SHADER\n"
1908 "\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR,\n"
1912 "float2 TexCoord1 : TEXCOORD0,\n"
1913 "float2 TexCoord2 : TEXCOORD1,\n"
1914 "#ifdef USEDIFFUSE\n"
1915 "uniform sampler2D Texture_First,\n"
1916 "#endif\n"
1917 "#ifdef USESPECULAR\n"
1918 "uniform sampler2D Texture_Second,\n"
1919 "#endif\n"
1920 "out float4 gl_FragColor : COLOR\n"
1921 ")\n"
1922 "{\n"
1923 "       gl_FragColor = gl_FrontColor;\n"
1924 "#ifdef USEDIFFUSE\n"
1925 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1926 "#endif\n"
1927 "\n"
1928 "#ifdef USESPECULAR\n"
1929 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1930 "# ifdef USECOLORMAPPING\n"
1931 "       gl_FragColor *= tex2;\n"
1932 "# endif\n"
1933 "# ifdef USEGLOW\n"
1934 "       gl_FragColor += tex2;\n"
1935 "# endif\n"
1936 "# ifdef USEVERTEXTEXTUREBLEND\n"
1937 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1938 "# endif\n"
1939 "#endif\n"
1940 "}\n"
1941 "#endif\n"
1942 "#else // !MODE_GENERIC\n"
1943 "\n"
1944 "\n"
1945 "\n"
1946 "\n"
1947 "#ifdef MODE_BLOOMBLUR\n"
1948 "#ifdef VERTEX_SHADER\n"
1949 "void main\n"
1950 "(\n"
1951 "float4 gl_Vertex : POSITION,\n"
1952 "uniform float4x4 ModelViewProjectionMatrix,\n"
1953 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1954 "out float4 gl_Position : POSITION,\n"
1955 "out float2 TexCoord : TEXCOORD0\n"
1956 ")\n"
1957 "{\n"
1958 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1959 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1960 "}\n"
1961 "#endif\n"
1962 "\n"
1963 "#ifdef FRAGMENT_SHADER\n"
1964 "\n"
1965 "void main\n"
1966 "(\n"
1967 "float2 TexCoord : TEXCOORD0,\n"
1968 "uniform sampler2D Texture_First,\n"
1969 "uniform float4 BloomBlur_Parameters,\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       int i;\n"
1974 "       float2 tc = TexCoord;\n"
1975 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
1976 "       tc += BloomBlur_Parameters.xy;\n"
1977 "       for (i = 1;i < SAMPLES;i++)\n"
1978 "       {\n"
1979 "               color += tex2D(Texture_First, tc).rgb;\n"
1980 "               tc += BloomBlur_Parameters.xy;\n"
1981 "       }\n"
1982 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
1983 "}\n"
1984 "#endif\n"
1985 "#else // !MODE_BLOOMBLUR\n"
1986 "#ifdef MODE_REFRACTION\n"
1987 "#ifdef VERTEX_SHADER\n"
1988 "void main\n"
1989 "(\n"
1990 "float4 gl_Vertex : POSITION,\n"
1991 "uniform float4x4 ModelViewProjectionMatrix,\n"
1992 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1993 "uniform float4x4 TexMatrix,\n"
1994 "uniform float3 EyePosition,\n"
1995 "out float4 gl_Position : POSITION,\n"
1996 "out float2 TexCoord : TEXCOORD0,\n"
1997 "out float3 EyeVector : TEXCOORD1,\n"
1998 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
1999 ")\n"
2000 "{\n"
2001 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2002 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2003 "       ModelViewProjectionPosition = gl_Position;\n"
2004 "}\n"
2005 "#endif\n"
2006 "\n"
2007 "#ifdef FRAGMENT_SHADER\n"
2008 "void main\n"
2009 "(\n"
2010 "float2 TexCoord : TEXCOORD0,\n"
2011 "float3 EyeVector : TEXCOORD1,\n"
2012 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2013 "uniform sampler2D Texture_Normal,\n"
2014 "uniform sampler2D Texture_Refraction,\n"
2015 "uniform sampler2D Texture_Reflection,\n"
2016 "uniform float4 DistortScaleRefractReflect,\n"
2017 "uniform float4 ScreenScaleRefractReflect,\n"
2018 "uniform float4 ScreenCenterRefractReflect,\n"
2019 "uniform float4 RefractColor,\n"
2020 "out float4 gl_FragColor : COLOR\n"
2021 ")\n"
2022 "{\n"
2023 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2024 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2025 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2026 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2027 "       // FIXME temporary hack to detect the case that the reflection\n"
2028 "       // gets blackened at edges due to leaving the area that contains actual\n"
2029 "       // content.\n"
2030 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2031 "       // 'appening.\n"
2032 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2033 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2034 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2035 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2036 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2037 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2038 "}\n"
2039 "#endif\n"
2040 "#else // !MODE_REFRACTION\n"
2041 "\n"
2042 "\n"
2043 "\n"
2044 "\n"
2045 "#ifdef MODE_WATER\n"
2046 "#ifdef VERTEX_SHADER\n"
2047 "\n"
2048 "void main\n"
2049 "(\n"
2050 "float4 gl_Vertex : POSITION,\n"
2051 "uniform float4x4 ModelViewProjectionMatrix,\n"
2052 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2053 "uniform float4x4 TexMatrix,\n"
2054 "uniform float3 EyePosition,\n"
2055 "out float4 gl_Position : POSITION,\n"
2056 "out float2 TexCoord : TEXCOORD0,\n"
2057 "out float3 EyeVector : TEXCOORD1,\n"
2058 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2059 ")\n"
2060 "{\n"
2061 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2062 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2063 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2064 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2065 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2066 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2067 "       ModelViewProjectionPosition = gl_Position;\n"
2068 "}\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef FRAGMENT_SHADER\n"
2072 "void main\n"
2073 "(\n"
2074 "float2 TexCoord : TEXCOORD0,\n"
2075 "float3 EyeVector : TEXCOORD1,\n"
2076 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2077 "uniform sampler2D Texture_Normal,\n"
2078 "uniform sampler2D Texture_Refraction,\n"
2079 "uniform sampler2D Texture_Reflection,\n"
2080 "uniform float4 DistortScaleRefractReflect,\n"
2081 "uniform float4 ScreenScaleRefractReflect,\n"
2082 "uniform float4 ScreenCenterRefractReflect,\n"
2083 "uniform float4 RefractColor,\n"
2084 "uniform float4 ReflectColor,\n"
2085 "uniform float ReflectFactor,\n"
2086 "uniform float ReflectOffset,\n"
2087 "out float4 gl_FragColor : COLOR\n"
2088 ")\n"
2089 "{\n"
2090 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2091 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2092 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2093 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2094 "       // FIXME temporary hack to detect the case that the reflection\n"
2095 "       // gets blackened at edges due to leaving the area that contains actual\n"
2096 "       // content.\n"
2097 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2098 "       // 'appening.\n"
2099 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2100 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2101 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2102 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2103 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2104 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2105 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2106 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2107 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2108 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2109 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2110 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2111 "}\n"
2112 "#endif\n"
2113 "#else // !MODE_WATER\n"
2114 "\n"
2115 "\n"
2116 "\n"
2117 "\n"
2118 "// 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"
2119 "\n"
2120 "// fragment shader specific:\n"
2121 "#ifdef FRAGMENT_SHADER\n"
2122 "\n"
2123 "#ifdef USEFOG\n"
2124 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2125 "{\n"
2126 "       float fogfrac;\n"
2127 "#ifdef USEFOGOUTSIDE\n"
2128 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2129 "#else\n"
2130 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2131 "#endif\n"
2132 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2133 "}\n"
2134 "#endif\n"
2135 "\n"
2136 "#ifdef USEOFFSETMAPPING\n"
2137 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2138 "{\n"
2139 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2140 "       // 14 sample relief mapping: linear search and then binary search\n"
2141 "       // this basically steps forward a small amount repeatedly until it finds\n"
2142 "       // itself inside solid, then jitters forward and back using decreasing\n"
2143 "       // amounts to find the impact\n"
2144 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2145 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2146 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2147 "       float3 RT = float3(TexCoord, 1);\n"
2148 "       OffsetVector *= 0.1;\n"
2149 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2150 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2151 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2152 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2153 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2154 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2155 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2156 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2157 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2158 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2159 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2160 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2161 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2162 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2163 "       return RT.xy;\n"
2164 "#else\n"
2165 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2166 "       // this basically moves forward the full distance, and then backs up based\n"
2167 "       // on height of samples\n"
2168 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2169 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2170 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2171 "       TexCoord += OffsetVector;\n"
2172 "       OffsetVector *= 0.333;\n"
2173 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2174 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2175 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2176 "       return TexCoord;\n"
2177 "#endif\n"
2178 "}\n"
2179 "#endif // USEOFFSETMAPPING\n"
2180 "\n"
2181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2182 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2183 "# ifdef USESHADOWMAPORTHO\n"
2184 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2185 "# else\n"
2186 "#  ifdef USESHADOWMAPVSDCT\n"
2187 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2188 "{\n"
2189 "       float3 adir = abs(dir);\n"
2190 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2191 "       float4 proj = texCUBEe(Texture_CubeProjection, dir);\n"
2192 "       return float3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2193 "}\n"
2194 "#  else\n"
2195 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2196 "{\n"
2197 "       float3 adir = abs(dir);\n"
2198 "       float ma = adir.z;\n"
2199 "       float4 proj = float4(dir, 2.5);\n"
2200 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2201 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2202 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2203 "       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"
2204 "}\n"
2205 "#  endif\n"
2206 "# endif\n"
2207 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPORTHO)\n"
2208 "\n"
2209 "#ifdef USESHADOWMAPCUBE\n"
2210 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2211 "{\n"
2212 "    float3 adir = abs(dir);\n"
2213 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2214 "}\n"
2215 "#endif\n"
2216 "\n"
2217 "# ifdef USESHADOWMAPRECT\n"
2218 "#ifdef USESHADOWMAPVSDCT\n"
2219 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2220 "#else\n"
2221 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2222 "#endif\n"
2223 "{\n"
2224 "#ifdef USESHADOWMAPVSDCT\n"
2225 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2226 "#else\n"
2227 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2228 "#endif\n"
2229 "       float f;\n"
2230 "#  ifdef USESHADOWSAMPLER\n"
2231 "\n"
2232 "#    ifdef USESHADOWMAPPCF\n"
2233 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2234 "    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"
2235 "#    else\n"
2236 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2237 "#    endif\n"
2238 "\n"
2239 "#  else\n"
2240 "\n"
2241 "#    ifdef USESHADOWMAPPCF\n"
2242 "#      if USESHADOWMAPPCF > 1\n"
2243 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2244 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2245 "    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"
2246 "    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"
2247 "    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"
2248 "    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"
2249 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2250 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2251 "#      else\n"
2252 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2253 "    float2 offset = frac(shadowmaptc.xy);\n"
2254 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2255 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2256 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2257 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2258 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2259 "#      endif\n"
2260 "#    else\n"
2261 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2262 "#    endif\n"
2263 "\n"
2264 "#  endif\n"
2265 "#  ifdef USESHADOWMAPORTHO\n"
2266 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2267 "#  else\n"
2268 "       return f;\n"
2269 "#  endif\n"
2270 "}\n"
2271 "# endif\n"
2272 "\n"
2273 "# ifdef USESHADOWMAP2D\n"
2274 "#ifdef USESHADOWMAPVSDCT\n"
2275 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2276 "#else\n"
2277 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2278 "#endif\n"
2279 "{\n"
2280 "#ifdef USESHADOWMAPVSDCT\n"
2281 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2282 "#else\n"
2283 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2284 "#endif\n"
2285 "    float f;\n"
2286 "\n"
2287 "#  ifdef USESHADOWSAMPLER\n"
2288 "#    ifdef USESHADOWMAPPCF\n"
2289 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2290 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2291 "    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"
2292 "#    else\n"
2293 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2294 "#    endif\n"
2295 "#  else\n"
2296 "#    ifdef USESHADOWMAPPCF\n"
2297 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2298 "#      ifdef GL_ARB_texture_gather\n"
2299 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2300 "#      else\n"
2301 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2302 "#      endif\n"
2303 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2304 "    center *= ShadowMap_TextureScale;\n"
2305 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2306 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2307 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2308 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2309 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2310 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2311 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2312 "#     else\n"
2313 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2314 "#      if USESHADOWMAPPCF > 1\n"
2315 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2316 "    center *= ShadowMap_TextureScale;\n"
2317 "    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"
2318 "    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"
2319 "    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"
2320 "    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"
2321 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2322 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2323 "#      else\n"
2324 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2325 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2326 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2327 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2328 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2329 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2330 "#      endif\n"
2331 "#     endif\n"
2332 "#    else\n"
2333 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2334 "#    endif\n"
2335 "#  endif\n"
2336 "#  ifdef USESHADOWMAPORTHO\n"
2337 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2338 "#  else\n"
2339 "       return f;\n"
2340 "#  endif\n"
2341 "}\n"
2342 "# endif\n"
2343 "\n"
2344 "# ifdef USESHADOWMAPCUBE\n"
2345 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2346 "{\n"
2347 "    // apply depth texture cubemap as light filter\n"
2348 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2349 "    float f;\n"
2350 "#  ifdef USESHADOWSAMPLER\n"
2351 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2352 "#  else\n"
2353 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2354 "#  endif\n"
2355 "    return f;\n"
2356 "}\n"
2357 "# endif\n"
2358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2359 "#endif // FRAGMENT_SHADER\n"
2360 "\n"
2361 "\n"
2362 "\n"
2363 "\n"
2364 "#ifdef MODE_DEFERREDGEOMETRY\n"
2365 "#ifdef VERTEX_SHADER\n"
2366 "void main\n"
2367 "(\n"
2368 "float4 gl_Vertex : POSITION,\n"
2369 "uniform float4x4 ModelViewProjectionMatrix,\n"
2370 "#ifdef USEVERTEXTEXTUREBLEND\n"
2371 "float4 gl_Color : COLOR0,\n"
2372 "#endif\n"
2373 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2374 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2375 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2376 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2377 "uniform float4x4 TexMatrix,\n"
2378 "#ifdef USEVERTEXTEXTUREBLEND\n"
2379 "uniform float4x4 BackgroundTexMatrix,\n"
2380 "#endif\n"
2381 "uniform float4x4 ModelViewMatrix,\n"
2382 "#ifdef USEOFFSETMAPPING\n"
2383 "uniform float3 EyePosition,\n"
2384 "#endif\n"
2385 "out float4 gl_Position : POSITION,\n"
2386 "out float4 gl_FrontColor : COLOR,\n"
2387 "out float4 TexCoordBoth : TEXCOORD0,\n"
2388 "#ifdef USEOFFSETMAPPING\n"
2389 "out float3 EyeVector : TEXCOORD2,\n"
2390 "#endif\n"
2391 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2392 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2393 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2394 ")\n"
2395 "{\n"
2396 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2397 "#ifdef USEVERTEXTEXTUREBLEND\n"
2398 "       gl_FrontColor = gl_Color;\n"
2399 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2400 "#endif\n"
2401 "\n"
2402 "       // transform unnormalized eye direction into tangent space\n"
2403 "#ifdef USEOFFSETMAPPING\n"
2404 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2405 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2406 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2407 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2408 "#endif\n"
2409 "\n"
2410 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2411 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2412 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2413 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2414 "}\n"
2415 "#endif // VERTEX_SHADER\n"
2416 "\n"
2417 "#ifdef FRAGMENT_SHADER\n"
2418 "void main\n"
2419 "(\n"
2420 "float4 TexCoordBoth : TEXCOORD0,\n"
2421 "float3 EyeVector : TEXCOORD2,\n"
2422 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2423 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2424 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2425 "uniform sampler2D Texture_Normal,\n"
2426 "#ifdef USEALPHAKILL\n"
2427 "uniform sampler2D Texture_Color,\n"
2428 "#endif\n"
2429 "uniform sampler2D Texture_Gloss,\n"
2430 "#ifdef USEVERTEXTEXTUREBLEND\n"
2431 "uniform sampler2D Texture_SecondaryNormal,\n"
2432 "uniform sampler2D Texture_SecondaryGloss,\n"
2433 "#endif\n"
2434 "#ifdef USEOFFSETMAPPING\n"
2435 "uniform float OffsetMapping_Scale,\n"
2436 "#endif\n"
2437 "uniform half SpecularPower,\n"
2438 "out float4 gl_FragColor : COLOR\n"
2439 ")\n"
2440 "{\n"
2441 "       float2 TexCoord = TexCoordBoth.xy;\n"
2442 "#ifdef USEOFFSETMAPPING\n"
2443 "       // apply offsetmapping\n"
2444 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2445 "#define TexCoord TexCoordOffset\n"
2446 "#endif\n"
2447 "\n"
2448 "#ifdef USEALPHAKILL\n"
2449 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2450 "               discard;\n"
2451 "#endif\n"
2452 "\n"
2453 "#ifdef USEVERTEXTEXTUREBLEND\n"
2454 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2455 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2456 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2457 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2458 "#endif\n"
2459 "\n"
2460 "#ifdef USEVERTEXTEXTUREBLEND\n"
2461 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2462 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2463 "#else\n"
2464 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2465 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2466 "#endif\n"
2467 "\n"
2468 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2469 "}\n"
2470 "#endif // FRAGMENT_SHADER\n"
2471 "#else // !MODE_DEFERREDGEOMETRY\n"
2472 "\n"
2473 "\n"
2474 "\n"
2475 "\n"
2476 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2477 "#ifdef VERTEX_SHADER\n"
2478 "void main\n"
2479 "(\n"
2480 "float4 gl_Vertex : POSITION,\n"
2481 "uniform float4x4 ModelViewProjectionMatrix,\n"
2482 "uniform float4x4 ModelViewMatrix,\n"
2483 "out float4 gl_Position : POSITION,\n"
2484 "out float4 ModelViewPosition : TEXCOORD0\n"
2485 ")\n"
2486 "{\n"
2487 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2488 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2489 "}\n"
2490 "#endif // VERTEX_SHADER\n"
2491 "\n"
2492 "#ifdef FRAGMENT_SHADER\n"
2493 "void main\n"
2494 "(\n"
2495 "float2 Pixel : WPOS,\n"
2496 "float4 ModelViewPosition : TEXCOORD0,\n"
2497 "uniform float4x4 ViewToLight,\n"
2498 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2499 "uniform float3 LightPosition,\n"
2500 "uniform half2 PixelToScreenTexCoord,\n"
2501 "uniform half3 DeferredColor_Ambient,\n"
2502 "uniform half3 DeferredColor_Diffuse,\n"
2503 "#ifdef USESPECULAR\n"
2504 "uniform half3 DeferredColor_Specular,\n"
2505 "uniform half SpecularPower,\n"
2506 "#endif\n"
2507 "uniform sampler2D Texture_Attenuation,\n"
2508 "uniform sampler2D Texture_ScreenDepth,\n"
2509 "uniform sampler2D Texture_ScreenNormalMap,\n"
2510 "\n"
2511 "#ifdef USESHADOWMAPRECT\n"
2512 "# ifdef USESHADOWSAMPLER\n"
2513 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2514 "# else\n"
2515 "uniform samplerRECT Texture_ShadowMapRect,\n"
2516 "# endif\n"
2517 "#endif\n"
2518 "\n"
2519 "#ifdef USESHADOWMAP2D\n"
2520 "# ifdef USESHADOWSAMPLER\n"
2521 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2522 "# else\n"
2523 "uniform sampler2D Texture_ShadowMap2D,\n"
2524 "# endif\n"
2525 "#endif\n"
2526 "\n"
2527 "#ifdef USESHADOWMAPVSDCT\n"
2528 "uniform samplerCUBE Texture_CubeProjection,\n"
2529 "#endif\n"
2530 "\n"
2531 "#ifdef USESHADOWMAPCUBE\n"
2532 "# ifdef USESHADOWSAMPLER\n"
2533 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2534 "# else\n"
2535 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2536 "# endif\n"
2537 "#endif\n"
2538 "\n"
2539 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2540 "uniform float2 ShadowMap_TextureScale,\n"
2541 "uniform float4 ShadowMap_Parameters,\n"
2542 "#endif\n"
2543 "\n"
2544 "out float4 gl_FragData0 : COLOR0,\n"
2545 "out float4 gl_FragData1 : COLOR1\n"
2546 ")\n"
2547 "{\n"
2548 "       // calculate viewspace pixel position\n"
2549 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2550 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2551 "       float3 position;\n"
2552 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2553 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2554 "       // decode viewspace pixel normal\n"
2555 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2556 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2557 "       // surfacenormal = pixel normal in viewspace\n"
2558 "       // LightVector = pixel to light in viewspace\n"
2559 "       // CubeVector = position in lightspace\n"
2560 "       // eyevector = pixel to view in viewspace\n"
2561 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2562 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2563 "#ifdef USEDIFFUSE\n"
2564 "       // calculate diffuse shading\n"
2565 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2566 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2567 "#endif\n"
2568 "#ifdef USESPECULAR\n"
2569 "       // calculate directional shading\n"
2570 "       float3 eyevector = position * -1.0;\n"
2571 "#  ifdef USEEXACTSPECULARMATH\n"
2572 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2573 "#  else\n"
2574 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2575 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2576 "#  endif\n"
2577 "#endif\n"
2578 "\n"
2579 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2580 "       fade *= ShadowMapCompare(CubeVector,\n"
2581 "# if defined(USESHADOWMAP2D)\n"
2582 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2583 "# endif\n"
2584 "# if defined(USESHADOWMAPRECT)\n"
2585 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2586 "# endif\n"
2587 "# if defined(USESHADOWMAPCUBE)\n"
2588 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2589 "# endif\n"
2590 "\n"
2591 "#ifdef USESHADOWMAPVSDCT\n"
2592 ", Texture_CubeProjection\n"
2593 "#endif\n"
2594 "       );\n"
2595 "#endif\n"
2596 "\n"
2597 "#ifdef USEDIFFUSE\n"
2598 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2599 "#else\n"
2600 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2601 "#endif\n"
2602 "#ifdef USESPECULAR\n"
2603 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2604 "#else\n"
2605 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2606 "#endif\n"
2607 "\n"
2608 "# ifdef USECUBEFILTER\n"
2609 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2610 "       gl_FragData0.rgb *= cubecolor;\n"
2611 "       gl_FragData1.rgb *= cubecolor;\n"
2612 "# endif\n"
2613 "}\n"
2614 "#endif // FRAGMENT_SHADER\n"
2615 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2616 "\n"
2617 "\n"
2618 "\n"
2619 "\n"
2620 "#ifdef VERTEX_SHADER\n"
2621 "void main\n"
2622 "(\n"
2623 "float4 gl_Vertex : POSITION,\n"
2624 "uniform float4x4 ModelViewProjectionMatrix,\n"
2625 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2626 "float4 gl_Color : COLOR0,\n"
2627 "#endif\n"
2628 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2629 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2630 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2631 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2632 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2633 "\n"
2634 "uniform float3 EyePosition,\n"
2635 "uniform float4x4 TexMatrix,\n"
2636 "#ifdef USEVERTEXTEXTUREBLEND\n"
2637 "uniform float4x4 BackgroundTexMatrix,\n"
2638 "#endif\n"
2639 "#ifdef MODE_LIGHTSOURCE\n"
2640 "uniform float4x4 ModelToLight,\n"
2641 "#endif\n"
2642 "#ifdef MODE_LIGHTSOURCE\n"
2643 "uniform float3 LightPosition,\n"
2644 "#endif\n"
2645 "#ifdef MODE_LIGHTDIRECTION\n"
2646 "uniform float3 LightDir,\n"
2647 "#endif\n"
2648 "uniform float4 FogPlane,\n"
2649 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2650 "uniform float3 LightPosition,\n"
2651 "#endif\n"
2652 "#ifdef USESHADOWMAPORTHO\n"
2653 "uniform float4x4 ShadowMapMatrix,\n"
2654 "#endif\n"
2655 "\n"
2656 "out float4 gl_FrontColor : COLOR,\n"
2657 "out float4 TexCoordBoth : TEXCOORD0,\n"
2658 "#ifdef USELIGHTMAP\n"
2659 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2660 "#endif\n"
2661 "#ifdef USEEYEVECTOR\n"
2662 "out float3 EyeVector : TEXCOORD2,\n"
2663 "#endif\n"
2664 "#ifdef USEREFLECTION\n"
2665 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2666 "#endif\n"
2667 "#ifdef USEFOG\n"
2668 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2669 "#endif\n"
2670 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2671 "out float3 LightVector : TEXCOORD5,\n"
2672 "#endif\n"
2673 "#ifdef MODE_LIGHTSOURCE\n"
2674 "out float3 CubeVector : TEXCOORD3,\n"
2675 "#endif\n"
2676 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2677 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2678 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2679 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2680 "#endif\n"
2681 "#ifdef USESHADOWMAPORTHO\n"
2682 "out float3 ShadowMapTC : TEXCOORD8,\n"
2683 "#endif\n"
2684 "out float4 gl_Position : POSITION\n"
2685 ")\n"
2686 "{\n"
2687 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2688 "       gl_FrontColor = gl_Color;\n"
2689 "#endif\n"
2690 "       // copy the surface texcoord\n"
2691 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2692 "#ifdef USEVERTEXTEXTUREBLEND\n"
2693 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2694 "#endif\n"
2695 "#ifdef USELIGHTMAP\n"
2696 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2697 "#endif\n"
2698 "\n"
2699 "#ifdef MODE_LIGHTSOURCE\n"
2700 "       // transform vertex position into light attenuation/cubemap space\n"
2701 "       // (-1 to +1 across the light box)\n"
2702 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2703 "\n"
2704 "# ifdef USEDIFFUSE\n"
2705 "       // transform unnormalized light direction into tangent space\n"
2706 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2707 "       //  normalize it per pixel)\n"
2708 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2709 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2710 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2711 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2712 "# endif\n"
2713 "#endif\n"
2714 "\n"
2715 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2716 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2717 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2718 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2719 "#endif\n"
2720 "\n"
2721 "       // transform unnormalized eye direction into tangent space\n"
2722 "#ifdef USEEYEVECTOR\n"
2723 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2724 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2725 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2726 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2727 "#endif\n"
2728 "\n"
2729 "#ifdef USEFOG\n"
2730 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2731 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2732 "#endif\n"
2733 "\n"
2734 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2735 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2736 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2737 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2738 "#endif\n"
2739 "\n"
2740 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2741 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2742 "\n"
2743 "#ifdef USESHADOWMAPORTHO\n"
2744 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2745 "#endif\n"
2746 "\n"
2747 "#ifdef USEREFLECTION\n"
2748 "       ModelViewProjectionPosition = gl_Position;\n"
2749 "#endif\n"
2750 "}\n"
2751 "#endif // VERTEX_SHADER\n"
2752 "\n"
2753 "\n"
2754 "\n"
2755 "\n"
2756 "#ifdef FRAGMENT_SHADER\n"
2757 "void main\n"
2758 "(\n"
2759 "#ifdef USEDEFERREDLIGHTMAP\n"
2760 "float2 Pixel : WPOS,\n"
2761 "#endif\n"
2762 "float4 gl_FrontColor : COLOR,\n"
2763 "float4 TexCoordBoth : TEXCOORD0,\n"
2764 "#ifdef USELIGHTMAP\n"
2765 "float2 TexCoordLightmap : TEXCOORD1,\n"
2766 "#endif\n"
2767 "#ifdef USEEYEVECTOR\n"
2768 "float3 EyeVector : TEXCOORD2,\n"
2769 "#endif\n"
2770 "#ifdef USEREFLECTION\n"
2771 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2772 "#endif\n"
2773 "#ifdef USEFOG\n"
2774 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2775 "#endif\n"
2776 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2777 "float3 LightVector : TEXCOORD5,\n"
2778 "#endif\n"
2779 "#ifdef MODE_LIGHTSOURCE\n"
2780 "float3 CubeVector : TEXCOORD3,\n"
2781 "#endif\n"
2782 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2783 "float4 ModelViewPosition : TEXCOORD0,\n"
2784 "#endif\n"
2785 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2786 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2787 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2788 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2789 "#endif\n"
2790 "#ifdef USESHADOWMAPORTHO\n"
2791 "float3 ShadowMapTC : TEXCOORD8\n"
2792 "#endif\n"
2793 "\n"
2794 "uniform sampler2D Texture_Normal,\n"
2795 "uniform sampler2D Texture_Color,\n"
2796 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2797 "uniform sampler2D Texture_Gloss,\n"
2798 "#endif\n"
2799 "#ifdef USEGLOW\n"
2800 "uniform sampler2D Texture_Glow,\n"
2801 "#endif\n"
2802 "#ifdef USEVERTEXTEXTUREBLEND\n"
2803 "uniform sampler2D Texture_SecondaryNormal,\n"
2804 "uniform sampler2D Texture_SecondaryColor,\n"
2805 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2806 "uniform sampler2D Texture_SecondaryGloss,\n"
2807 "#endif\n"
2808 "#ifdef USEGLOW\n"
2809 "uniform sampler2D Texture_SecondaryGlow,\n"
2810 "#endif\n"
2811 "#endif\n"
2812 "#ifdef USECOLORMAPPING\n"
2813 "uniform sampler2D Texture_Pants,\n"
2814 "uniform sampler2D Texture_Shirt,\n"
2815 "#endif\n"
2816 "#ifdef USEFOG\n"
2817 "uniform sampler2D Texture_FogMask,\n"
2818 "#endif\n"
2819 "#ifdef USELIGHTMAP\n"
2820 "uniform sampler2D Texture_Lightmap,\n"
2821 "#endif\n"
2822 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2823 "uniform sampler2D Texture_Deluxemap,\n"
2824 "#endif\n"
2825 "#ifdef USEREFLECTION\n"
2826 "uniform sampler2D Texture_Reflection,\n"
2827 "#endif\n"
2828 "\n"
2829 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2830 "uniform sampler2D Texture_ScreenDepth,\n"
2831 "uniform sampler2D Texture_ScreenNormalMap,\n"
2832 "#endif\n"
2833 "#ifdef USEDEFERREDLIGHTMAP\n"
2834 "uniform sampler2D Texture_ScreenDiffuse,\n"
2835 "uniform sampler2D Texture_ScreenSpecular,\n"
2836 "#endif\n"
2837 "\n"
2838 "#ifdef USECOLORMAPPING\n"
2839 "uniform half3 Color_Pants,\n"
2840 "uniform half3 Color_Shirt,\n"
2841 "#endif\n"
2842 "#ifdef USEFOG\n"
2843 "uniform float3 FogColor,\n"
2844 "uniform float FogRangeRecip,\n"
2845 "uniform float FogPlaneViewDist,\n"
2846 "uniform float FogHeightFade,\n"
2847 "#endif\n"
2848 "\n"
2849 "#ifdef USEOFFSETMAPPING\n"
2850 "uniform float OffsetMapping_Scale,\n"
2851 "#endif\n"
2852 "\n"
2853 "#ifdef USEDEFERREDLIGHTMAP\n"
2854 "uniform half2 PixelToScreenTexCoord,\n"
2855 "uniform half3 DeferredMod_Diffuse,\n"
2856 "uniform half3 DeferredMod_Specular,\n"
2857 "#endif\n"
2858 "uniform half3 Color_Ambient,\n"
2859 "uniform half3 Color_Diffuse,\n"
2860 "uniform half3 Color_Specular,\n"
2861 "uniform half SpecularPower,\n"
2862 "#ifdef USEGLOW\n"
2863 "uniform half3 Color_Glow,\n"
2864 "#endif\n"
2865 "uniform half Alpha,\n"
2866 "#ifdef USEREFLECTION\n"
2867 "uniform float4 DistortScaleRefractReflect,\n"
2868 "uniform float4 ScreenScaleRefractReflect,\n"
2869 "uniform float4 ScreenCenterRefractReflect,\n"
2870 "uniform half4 ReflectColor,\n"
2871 "#endif\n"
2872 "#ifdef USEREFLECTCUBE\n"
2873 "uniform float4x4 ModelToReflectCube,\n"
2874 "uniform sampler2D Texture_ReflectMask,\n"
2875 "uniform samplerCUBE Texture_ReflectCube,\n"
2876 "#endif\n"
2877 "#ifdef MODE_LIGHTDIRECTION\n"
2878 "uniform half3 LightColor,\n"
2879 "#endif\n"
2880 "#ifdef MODE_LIGHTSOURCE\n"
2881 "uniform half3 LightColor,\n"
2882 "#endif\n"
2883 "\n"
2884 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2885 "uniform sampler2D Texture_Attenuation,\n"
2886 "uniform samplerCUBE Texture_Cube,\n"
2887 "#endif\n"
2888 "\n"
2889 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2890 "\n"
2891 "#ifdef USESHADOWMAPRECT\n"
2892 "# ifdef USESHADOWSAMPLER\n"
2893 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2894 "# else\n"
2895 "uniform samplerRECT Texture_ShadowMapRect,\n"
2896 "# endif\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USESHADOWMAP2D\n"
2900 "# ifdef USESHADOWSAMPLER\n"
2901 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2902 "# else\n"
2903 "uniform sampler2D Texture_ShadowMap2D,\n"
2904 "# endif\n"
2905 "#endif\n"
2906 "\n"
2907 "#ifdef USESHADOWMAPVSDCT\n"
2908 "uniform samplerCUBE Texture_CubeProjection,\n"
2909 "#endif\n"
2910 "\n"
2911 "#ifdef USESHADOWMAPCUBE\n"
2912 "# ifdef USESHADOWSAMPLER\n"
2913 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2914 "# else\n"
2915 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2916 "# endif\n"
2917 "#endif\n"
2918 "\n"
2919 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2920 "uniform float2 ShadowMap_TextureScale,\n"
2921 "uniform float4 ShadowMap_Parameters,\n"
2922 "#endif\n"
2923 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2924 "\n"
2925 "out float4 gl_FragColor : COLOR\n"
2926 ")\n"
2927 "{\n"
2928 "       float2 TexCoord = TexCoordBoth.xy;\n"
2929 "#ifdef USEVERTEXTEXTUREBLEND\n"
2930 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2931 "#endif\n"
2932 "#ifdef USEOFFSETMAPPING\n"
2933 "       // apply offsetmapping\n"
2934 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2935 "#define TexCoord TexCoordOffset\n"
2936 "#endif\n"
2937 "\n"
2938 "       // combine the diffuse textures (base, pants, shirt)\n"
2939 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2940 "#ifdef USEALPHAKILL\n"
2941 "       if (color.a < 0.5)\n"
2942 "               discard;\n"
2943 "#endif\n"
2944 "       color.a *= Alpha;\n"
2945 "#ifdef USECOLORMAPPING\n"
2946 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2947 "#endif\n"
2948 "#ifdef USEVERTEXTEXTUREBLEND\n"
2949 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2950 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2951 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2952 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2953 "       color.a = 1.0;\n"
2954 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2955 "#endif\n"
2956 "\n"
2957 "       // get the surface normal\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2960 "#else\n"
2961 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
2962 "#endif\n"
2963 "\n"
2964 "       // get the material colors\n"
2965 "       half3 diffusetex = color.rgb;\n"
2966 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2967 "# ifdef USEVERTEXTEXTUREBLEND\n"
2968 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
2969 "# else\n"
2970 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
2971 "# endif\n"
2972 "#endif\n"
2973 "\n"
2974 "#ifdef USEREFLECTCUBE\n"
2975 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
2976 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
2977 "       vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
2978 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
2979 "#endif\n"
2980 "\n"
2981 "\n"
2982 "\n"
2983 "\n"
2984 "#ifdef MODE_LIGHTSOURCE\n"
2985 "       // light source\n"
2986 "#ifdef USEDIFFUSE\n"
2987 "       half3 lightnormal = half3(normalize(LightVector));\n"
2988 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2989 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
2990 "#ifdef USESPECULAR\n"
2991 "#ifdef USEEXACTSPECULARMATH\n"
2992 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
2993 "#else\n"
2994 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
2995 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
2996 "#endif\n"
2997 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
2998 "#endif\n"
2999 "#else\n"
3000 "       color.rgb = diffusetex * Color_Ambient;\n"
3001 "#endif\n"
3002 "       color.rgb *= LightColor;\n"
3003 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3004 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3005 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3006 "# if defined(USESHADOWMAP2D)\n"
3007 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3008 "# endif\n"
3009 "# if defined(USESHADOWMAPRECT)\n"
3010 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3011 "# endif\n"
3012 "# if defined(USESHADOWMAPCUBE)\n"
3013 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3014 "# endif\n"
3015 "\n"
3016 "#ifdef USESHADOWMAPVSDCT\n"
3017 ", Texture_CubeProjection\n"
3018 "#endif\n"
3019 "       );\n"
3020 "\n"
3021 "#endif\n"
3022 "# ifdef USECUBEFILTER\n"
3023 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3024 "# endif\n"
3025 "#endif // MODE_LIGHTSOURCE\n"
3026 "\n"
3027 "\n"
3028 "\n"
3029 "\n"
3030 "#ifdef MODE_LIGHTDIRECTION\n"
3031 "#define SHADING\n"
3032 "#ifdef USEDIFFUSE\n"
3033 "       half3 lightnormal = half3(normalize(LightVector));\n"
3034 "#endif\n"
3035 "#define lightcolor LightColor\n"
3036 "#endif // MODE_LIGHTDIRECTION\n"
3037 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3038 "#define SHADING\n"
3039 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3040 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3041 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3042 "       // convert modelspace light vector to tangentspace\n"
3043 "       half3 lightnormal;\n"
3044 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3045 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3046 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3047 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3048 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3049 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3050 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3051 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3052 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3053 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3054 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3055 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3056 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3057 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3058 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3059 "#define SHADING\n"
3060 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3061 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3062 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3063 "#endif\n"
3064 "\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "#ifdef MODE_LIGHTMAP\n"
3069 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3070 "#endif // MODE_LIGHTMAP\n"
3071 "#ifdef MODE_VERTEXCOLOR\n"
3072 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3073 "#endif // MODE_VERTEXCOLOR\n"
3074 "#ifdef MODE_FLATCOLOR\n"
3075 "       color.rgb = diffusetex * Color_Ambient;\n"
3076 "#endif // MODE_FLATCOLOR\n"
3077 "\n"
3078 "\n"
3079 "\n"
3080 "\n"
3081 "#ifdef SHADING\n"
3082 "# ifdef USEDIFFUSE\n"
3083 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3084 "#  ifdef USESPECULAR\n"
3085 "#   ifdef USEEXACTSPECULARMATH\n"
3086 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3087 "#   else\n"
3088 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3089 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3090 "#   endif\n"
3091 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3092 "#  else\n"
3093 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3094 "#  endif\n"
3095 "# else\n"
3096 "       color.rgb = diffusetex * Color_Ambient;\n"
3097 "# endif\n"
3098 "#endif\n"
3099 "\n"
3100 "#ifdef USESHADOWMAPORTHO\n"
3101 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3102 "# if defined(USESHADOWMAP2D)\n"
3103 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3104 "# endif\n"
3105 "# if defined(USESHADOWMAPRECT)\n"
3106 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3107 "# endif\n"
3108 "       );\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USEDEFERREDLIGHTMAP\n"
3112 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3113 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3114 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3115 "#endif\n"
3116 "\n"
3117 "#ifdef USEGLOW\n"
3118 "#ifdef USEVERTEXTEXTUREBLEND\n"
3119 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3120 "#else\n"
3121 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3122 "#endif\n"
3123 "#endif\n"
3124 "\n"
3125 "#ifdef USEFOG\n"
3126 "#ifdef MODE_LIGHTSOURCE\n"
3127 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3128 "#else\n"
3129 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3130 "#endif\n"
3131 "#endif\n"
3132 "\n"
3133 "       // 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"
3134 "#ifdef USEREFLECTION\n"
3135 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3136 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3137 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3138 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3139 "       // FIXME temporary hack to detect the case that the reflection\n"
3140 "       // gets blackened at edges due to leaving the area that contains actual\n"
3141 "       // content.\n"
3142 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3143 "       // 'appening.\n"
3144 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3145 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3146 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3147 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3148 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3149 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3150 "#endif\n"
3151 "\n"
3152 "       gl_FragColor = float4(color);\n"
3153 "}\n"
3154 "#endif // FRAGMENT_SHADER\n"
3155 "\n"
3156 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3157 "#endif // !MODE_DEFERREDGEOMETRY\n"
3158 "#endif // !MODE_WATER\n"
3159 "#endif // !MODE_REFRACTION\n"
3160 "#endif // !MODE_BLOOMBLUR\n"
3161 "#endif // !MODE_GENERIC\n"
3162 "#endif // !MODE_POSTPROCESS\n"
3163 "#endif // !MODE_SHOWDEPTH\n"
3164 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3165 ;
3166
3167 char *glslshaderstring = NULL;
3168 char *cgshaderstring = NULL;
3169
3170 //=======================================================================================================================================================
3171
3172 typedef struct shaderpermutationinfo_s
3173 {
3174         const char *pretext;
3175         const char *name;
3176 }
3177 shaderpermutationinfo_t;
3178
3179 typedef struct shadermodeinfo_s
3180 {
3181         const char *vertexfilename;
3182         const char *geometryfilename;
3183         const char *fragmentfilename;
3184         const char *pretext;
3185         const char *name;
3186 }
3187 shadermodeinfo_t;
3188
3189 typedef enum shaderpermutation_e
3190 {
3191         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3192         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3193         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3194         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3195         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3196         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3197         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3198         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3199         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3200         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3201         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3202         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3203         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3204         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3205         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3206         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3207         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3208         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3209         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3210         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3211         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3212         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3213         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3214         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3215         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3216         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3217         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3218         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3219         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3220         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3221 }
3222 shaderpermutation_t;
3223
3224 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3225 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3226 {
3227         {"#define USEDIFFUSE\n", " diffuse"},
3228         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3229         {"#define USEVIEWTINT\n", " viewtint"},
3230         {"#define USECOLORMAPPING\n", " colormapping"},
3231         {"#define USESATURATION\n", " saturation"},
3232         {"#define USEFOGINSIDE\n", " foginside"},
3233         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3234         {"#define USEGAMMARAMPS\n", " gammaramps"},
3235         {"#define USECUBEFILTER\n", " cubefilter"},
3236         {"#define USEGLOW\n", " glow"},
3237         {"#define USEBLOOM\n", " bloom"},
3238         {"#define USESPECULAR\n", " specular"},
3239         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3240         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3241         {"#define USEREFLECTION\n", " reflection"},
3242         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3243         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3244         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3245         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3246         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3247         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3248         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3249         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3250         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3251         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3252         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3253         {"#define USEALPHAKILL\n", " alphakill"},
3254         {"#define USEREFLECTCUBE\n", " reflectcube"},
3255 };
3256
3257 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3258 typedef enum shadermode_e
3259 {
3260         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3261         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3262         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3263         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3264         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3265         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3266         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3267         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3268         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3269         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3270         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3271         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3272         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3273         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3274         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3275         SHADERMODE_COUNT
3276 }
3277 shadermode_t;
3278
3279 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3280 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3281 {
3282         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3283         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3284         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3285         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3286         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3287         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3288         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3289         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3290         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3291         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3292         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3293         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3294         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3295         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3296         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3297 };
3298
3299 #ifdef SUPPORTCG
3300 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3301 {
3302         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3303         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3304         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3305         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3306         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3307         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3308         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3309         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3310         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3311         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3312         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3313         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3314         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3315         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3316         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3317 };
3318 #endif
3319
3320 struct r_glsl_permutation_s;
3321 typedef struct r_glsl_permutation_s
3322 {
3323         /// hash lookup data
3324         struct r_glsl_permutation_s *hashnext;
3325         unsigned int mode;
3326         unsigned int permutation;
3327
3328         /// indicates if we have tried compiling this permutation already
3329         qboolean compiled;
3330         /// 0 if compilation failed
3331         int program;
3332         /// locations of detected uniforms in program object, or -1 if not found
3333         int loc_Texture_First;
3334         int loc_Texture_Second;
3335         int loc_Texture_GammaRamps;
3336         int loc_Texture_Normal;
3337         int loc_Texture_Color;
3338         int loc_Texture_Gloss;
3339         int loc_Texture_Glow;
3340         int loc_Texture_SecondaryNormal;
3341         int loc_Texture_SecondaryColor;
3342         int loc_Texture_SecondaryGloss;
3343         int loc_Texture_SecondaryGlow;
3344         int loc_Texture_Pants;
3345         int loc_Texture_Shirt;
3346         int loc_Texture_FogMask;
3347         int loc_Texture_Lightmap;
3348         int loc_Texture_Deluxemap;
3349         int loc_Texture_Attenuation;
3350         int loc_Texture_Cube;
3351         int loc_Texture_Refraction;
3352         int loc_Texture_Reflection;
3353         int loc_Texture_ShadowMapRect;
3354         int loc_Texture_ShadowMapCube;
3355         int loc_Texture_ShadowMap2D;
3356         int loc_Texture_CubeProjection;
3357         int loc_Texture_ScreenDepth;
3358         int loc_Texture_ScreenNormalMap;
3359         int loc_Texture_ScreenDiffuse;
3360         int loc_Texture_ScreenSpecular;
3361         int loc_Texture_ReflectMask;
3362         int loc_Texture_ReflectCube;
3363         int loc_Alpha;
3364         int loc_BloomBlur_Parameters;
3365         int loc_ClientTime;
3366         int loc_Color_Ambient;
3367         int loc_Color_Diffuse;
3368         int loc_Color_Specular;
3369         int loc_Color_Glow;
3370         int loc_Color_Pants;
3371         int loc_Color_Shirt;
3372         int loc_DeferredColor_Ambient;
3373         int loc_DeferredColor_Diffuse;
3374         int loc_DeferredColor_Specular;
3375         int loc_DeferredMod_Diffuse;
3376         int loc_DeferredMod_Specular;
3377         int loc_DistortScaleRefractReflect;
3378         int loc_EyePosition;
3379         int loc_FogColor;
3380         int loc_FogHeightFade;
3381         int loc_FogPlane;
3382         int loc_FogPlaneViewDist;
3383         int loc_FogRangeRecip;
3384         int loc_LightColor;
3385         int loc_LightDir;
3386         int loc_LightPosition;
3387         int loc_OffsetMapping_Scale;
3388         int loc_PixelSize;
3389         int loc_ReflectColor;
3390         int loc_ReflectFactor;
3391         int loc_ReflectOffset;
3392         int loc_RefractColor;
3393         int loc_Saturation;
3394         int loc_ScreenCenterRefractReflect;
3395         int loc_ScreenScaleRefractReflect;
3396         int loc_ScreenToDepth;
3397         int loc_ShadowMap_Parameters;
3398         int loc_ShadowMap_TextureScale;
3399         int loc_SpecularPower;
3400         int loc_UserVec1;
3401         int loc_UserVec2;
3402         int loc_UserVec3;
3403         int loc_UserVec4;
3404         int loc_ViewTintColor;
3405         int loc_ViewToLight;
3406         int loc_ModelToLight;
3407         int loc_TexMatrix;
3408         int loc_BackgroundTexMatrix;
3409         int loc_ModelViewProjectionMatrix;
3410         int loc_ModelViewMatrix;
3411         int loc_PixelToScreenTexCoord;
3412         int loc_ModelToReflectCube;
3413         int loc_ShadowMapMatrix;        
3414 }
3415 r_glsl_permutation_t;
3416
3417 #define SHADERPERMUTATION_HASHSIZE 256
3418
3419 /// information about each possible shader permutation
3420 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3421 /// currently selected permutation
3422 r_glsl_permutation_t *r_glsl_permutation;
3423 /// storage for permutations linked in the hash table
3424 memexpandablearray_t r_glsl_permutationarray;
3425
3426 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3427 {
3428         //unsigned int hashdepth = 0;
3429         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3430         r_glsl_permutation_t *p;
3431         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3432         {
3433                 if (p->mode == mode && p->permutation == permutation)
3434                 {
3435                         //if (hashdepth > 10)
3436                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3437                         return p;
3438                 }
3439                 //hashdepth++;
3440         }
3441         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3442         p->mode = mode;
3443         p->permutation = permutation;
3444         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3445         r_glsl_permutationhash[mode][hashindex] = p;
3446         //if (hashdepth > 10)
3447         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3448         return p;
3449 }
3450
3451 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3452 {
3453         char *shaderstring;
3454         if (!filename || !filename[0])
3455                 return NULL;
3456         if (!strcmp(filename, "glsl/default.glsl"))
3457         {
3458                 if (!glslshaderstring)
3459                 {
3460                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3461                         if (glslshaderstring)
3462                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3463                         else
3464                                 glslshaderstring = (char *)builtinshaderstring;
3465                 }
3466                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3467                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3468                 return shaderstring;
3469         }
3470         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3471         if (shaderstring)
3472         {
3473                 if (printfromdisknotice)
3474                         Con_DPrintf("from disk %s... ", filename);
3475                 return shaderstring;
3476         }
3477         return shaderstring;
3478 }
3479
3480 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3481 {
3482         int i;
3483         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3484         int vertstrings_count = 0;
3485         int geomstrings_count = 0;
3486         int fragstrings_count = 0;
3487         char *vertexstring, *geometrystring, *fragmentstring;
3488         const char *vertstrings_list[32+3];
3489         const char *geomstrings_list[32+3];
3490         const char *fragstrings_list[32+3];
3491         char permutationname[256];
3492
3493         if (p->compiled)
3494                 return;
3495         p->compiled = true;
3496         p->program = 0;
3497
3498         permutationname[0] = 0;
3499         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3500         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3501         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3502
3503         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3504
3505         // the first pretext is which type of shader to compile as
3506         // (later these will all be bound together as a program object)
3507         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3508         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3509         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3510
3511         // the second pretext is the mode (for example a light source)
3512         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3513         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3514         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3515         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3516
3517         // now add all the permutation pretexts
3518         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3519         {
3520                 if (permutation & (1<<i))
3521                 {
3522                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3523                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3524                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3525                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3526                 }
3527                 else
3528                 {
3529                         // keep line numbers correct
3530                         vertstrings_list[vertstrings_count++] = "\n";
3531                         geomstrings_list[geomstrings_count++] = "\n";
3532                         fragstrings_list[fragstrings_count++] = "\n";
3533                 }
3534         }
3535
3536         // now append the shader text itself
3537         vertstrings_list[vertstrings_count++] = vertexstring;
3538         geomstrings_list[geomstrings_count++] = geometrystring;
3539         fragstrings_list[fragstrings_count++] = fragmentstring;
3540
3541         // if any sources were NULL, clear the respective list
3542         if (!vertexstring)
3543                 vertstrings_count = 0;
3544         if (!geometrystring)
3545                 geomstrings_count = 0;
3546         if (!fragmentstring)
3547                 fragstrings_count = 0;
3548
3549         // compile the shader program
3550         if (vertstrings_count + geomstrings_count + fragstrings_count)
3551                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3552         if (p->program)
3553         {
3554                 CHECKGLERROR
3555                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3556                 // look up all the uniform variable names we care about, so we don't
3557                 // have to look them up every time we set them
3558
3559                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3560                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3561                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3562                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3563                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3564                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3565                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3566                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3567                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3568                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3569                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3570                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3571                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3572                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3573                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3574                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3575                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3576                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3577                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3578                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3579                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3580                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3581                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3582                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3583                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3584                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3585                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3586                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3587                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3588                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3589                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3590                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3591                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3592                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3593                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3594                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3595                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3596                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3597                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3598                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3599                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3600                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3601                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3602                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3603                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3604                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3605                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3606                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3607                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3608                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3609                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3610                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3611                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3612                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3613                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3614                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3615                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3616                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3617                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3618                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3619                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3620                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3621                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3622                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3623                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3624                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3625                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3626                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3627                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3628                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3629                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3630                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3631                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3632                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3633                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3634                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3635                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3636                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3637                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3638                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3639                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3640                 // initialize the samplers to refer to the texture units we use
3641                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3642                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3643                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3644                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3645                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3646                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3647                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3648                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3649                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3650                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3651                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3652                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3653                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3654                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3655                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3656                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3657                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3658                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3659                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3660                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3661                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3662                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3663                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3664                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3665                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3666                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3667                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3668                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3669                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3670                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3671                 CHECKGLERROR
3672                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3673         }
3674         else
3675                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3676
3677         // free the strings
3678         if (vertexstring)
3679                 Mem_Free(vertexstring);
3680         if (geometrystring)
3681                 Mem_Free(geometrystring);
3682         if (fragmentstring)
3683                 Mem_Free(fragmentstring);
3684 }
3685
3686 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3687 {
3688         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3689         if (r_glsl_permutation != perm)
3690         {
3691                 r_glsl_permutation = perm;
3692                 if (!r_glsl_permutation->program)
3693                 {
3694                         if (!r_glsl_permutation->compiled)
3695                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3696                         if (!r_glsl_permutation->program)
3697                         {
3698                                 // remove features until we find a valid permutation
3699                                 int i;
3700                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3701                                 {
3702                                         // reduce i more quickly whenever it would not remove any bits
3703                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3704                                         if (!(permutation & j))
3705                                                 continue;
3706                                         permutation -= j;
3707                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3708                                         if (!r_glsl_permutation->compiled)
3709                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3710                                         if (r_glsl_permutation->program)
3711                                                 break;
3712                                 }
3713                                 if (i >= SHADERPERMUTATION_COUNT)
3714                                 {
3715                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3716                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3717                                         qglUseProgramObjectARB(0);CHECKGLERROR
3718                                         return; // no bit left to clear, entire mode is broken
3719                                 }
3720                         }
3721                 }
3722                 CHECKGLERROR
3723                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3724         }
3725         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3726         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3727         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3728 }
3729
3730 #ifdef SUPPORTCG
3731 #include <Cg/cgGL.h>
3732 struct r_cg_permutation_s;
3733 typedef struct r_cg_permutation_s
3734 {
3735         /// hash lookup data
3736         struct r_cg_permutation_s *hashnext;
3737         unsigned int mode;
3738         unsigned int permutation;
3739
3740         /// indicates if we have tried compiling this permutation already
3741         qboolean compiled;
3742         /// 0 if compilation failed
3743         CGprogram vprogram;
3744         CGprogram fprogram;
3745         /// locations of detected parameters in programs, or NULL if not found
3746         CGparameter vp_EyePosition;
3747         CGparameter vp_FogPlane;
3748         CGparameter vp_LightDir;
3749         CGparameter vp_LightPosition;
3750         CGparameter vp_ModelToLight;
3751         CGparameter vp_TexMatrix;
3752         CGparameter vp_BackgroundTexMatrix;
3753         CGparameter vp_ModelViewProjectionMatrix;
3754         CGparameter vp_ModelViewMatrix;
3755         CGparameter vp_ShadowMapMatrix;
3756
3757         CGparameter fp_Texture_First;
3758         CGparameter fp_Texture_Second;
3759         CGparameter fp_Texture_GammaRamps;
3760         CGparameter fp_Texture_Normal;
3761         CGparameter fp_Texture_Color;
3762         CGparameter fp_Texture_Gloss;
3763         CGparameter fp_Texture_Glow;
3764         CGparameter fp_Texture_SecondaryNormal;
3765         CGparameter fp_Texture_SecondaryColor;
3766         CGparameter fp_Texture_SecondaryGloss;
3767         CGparameter fp_Texture_SecondaryGlow;
3768         CGparameter fp_Texture_Pants;
3769         CGparameter fp_Texture_Shirt;
3770         CGparameter fp_Texture_FogMask;
3771         CGparameter fp_Texture_Lightmap;
3772         CGparameter fp_Texture_Deluxemap;
3773         CGparameter fp_Texture_Attenuation;
3774         CGparameter fp_Texture_Cube;
3775         CGparameter fp_Texture_Refraction;
3776         CGparameter fp_Texture_Reflection;
3777         CGparameter fp_Texture_ShadowMapRect;
3778         CGparameter fp_Texture_ShadowMapCube;
3779         CGparameter fp_Texture_ShadowMap2D;
3780         CGparameter fp_Texture_CubeProjection;
3781         CGparameter fp_Texture_ScreenDepth;
3782         CGparameter fp_Texture_ScreenNormalMap;
3783         CGparameter fp_Texture_ScreenDiffuse;
3784         CGparameter fp_Texture_ScreenSpecular;
3785         CGparameter fp_Texture_ReflectMask;
3786         CGparameter fp_Texture_ReflectCube;
3787         CGparameter fp_Alpha;
3788         CGparameter fp_BloomBlur_Parameters;
3789         CGparameter fp_ClientTime;
3790         CGparameter fp_Color_Ambient;
3791         CGparameter fp_Color_Diffuse;
3792         CGparameter fp_Color_Specular;
3793         CGparameter fp_Color_Glow;
3794         CGparameter fp_Color_Pants;
3795         CGparameter fp_Color_Shirt;
3796         CGparameter fp_DeferredColor_Ambient;
3797         CGparameter fp_DeferredColor_Diffuse;
3798         CGparameter fp_DeferredColor_Specular;
3799         CGparameter fp_DeferredMod_Diffuse;
3800         CGparameter fp_DeferredMod_Specular;
3801         CGparameter fp_DistortScaleRefractReflect;
3802         CGparameter fp_EyePosition;
3803         CGparameter fp_FogColor;
3804         CGparameter fp_FogHeightFade;
3805         CGparameter fp_FogPlane;
3806         CGparameter fp_FogPlaneViewDist;
3807         CGparameter fp_FogRangeRecip;
3808         CGparameter fp_LightColor;
3809         CGparameter fp_LightDir;
3810         CGparameter fp_LightPosition;
3811         CGparameter fp_OffsetMapping_Scale;
3812         CGparameter fp_PixelSize;
3813         CGparameter fp_ReflectColor;
3814         CGparameter fp_ReflectFactor;
3815         CGparameter fp_ReflectOffset;
3816         CGparameter fp_RefractColor;
3817         CGparameter fp_Saturation;
3818         CGparameter fp_ScreenCenterRefractReflect;
3819         CGparameter fp_ScreenScaleRefractReflect;
3820         CGparameter fp_ScreenToDepth;
3821         CGparameter fp_ShadowMap_Parameters;
3822         CGparameter fp_ShadowMap_TextureScale;
3823         CGparameter fp_SpecularPower;
3824         CGparameter fp_UserVec1;
3825         CGparameter fp_UserVec2;
3826         CGparameter fp_UserVec3;
3827         CGparameter fp_UserVec4;
3828         CGparameter fp_ViewTintColor;
3829         CGparameter fp_ViewToLight;
3830         CGparameter fp_PixelToScreenTexCoord;
3831         CGparameter fp_ModelToReflectCube;
3832 }
3833 r_cg_permutation_t;
3834
3835 /// information about each possible shader permutation
3836 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3837 /// currently selected permutation
3838 r_cg_permutation_t *r_cg_permutation;
3839 /// storage for permutations linked in the hash table
3840 memexpandablearray_t r_cg_permutationarray;
3841
3842 #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));}}
3843
3844 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3845 {
3846         //unsigned int hashdepth = 0;
3847         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3848         r_cg_permutation_t *p;
3849         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3850         {
3851                 if (p->mode == mode && p->permutation == permutation)
3852                 {
3853                         //if (hashdepth > 10)
3854                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3855                         return p;
3856                 }
3857                 //hashdepth++;
3858         }
3859         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3860         p->mode = mode;
3861         p->permutation = permutation;
3862         p->hashnext = r_cg_permutationhash[mode][hashindex];
3863         r_cg_permutationhash[mode][hashindex] = p;
3864         //if (hashdepth > 10)
3865         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3866         return p;
3867 }
3868
3869 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3870 {
3871         char *shaderstring;
3872         if (!filename || !filename[0])
3873                 return NULL;
3874         if (!strcmp(filename, "cg/default.cg"))
3875         {
3876                 if (!cgshaderstring)
3877                 {
3878                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3879                         if (cgshaderstring)
3880                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3881                         else
3882                                 cgshaderstring = (char *)builtincgshaderstring;
3883                 }
3884                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3885                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3886                 return shaderstring;
3887         }
3888         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3889         if (shaderstring)
3890         {
3891                 if (printfromdisknotice)
3892                         Con_DPrintf("from disk %s... ", filename);
3893                 return shaderstring;
3894         }
3895         return shaderstring;
3896 }
3897
3898 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3899 {
3900         // TODO: load or create .fp and .vp shader files
3901 }
3902
3903 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3904 {
3905         int i;
3906         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3907         int vertstrings_count = 0, vertstring_length = 0;
3908         int geomstrings_count = 0, geomstring_length = 0;
3909         int fragstrings_count = 0, fragstring_length = 0;
3910         char *t;
3911         char *vertexstring, *geometrystring, *fragmentstring;
3912         char *vertstring, *geomstring, *fragstring;
3913         const char *vertstrings_list[32+3];
3914         const char *geomstrings_list[32+3];
3915         const char *fragstrings_list[32+3];
3916         char permutationname[256];
3917         char cachename[256];
3918         CGprofile vertexProfile;
3919         CGprofile fragmentProfile;
3920
3921         if (p->compiled)
3922                 return;
3923         p->compiled = true;
3924         p->vprogram = NULL;
3925         p->fprogram = NULL;
3926
3927         permutationname[0] = 0;
3928         cachename[0] = 0;
3929         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3930         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3931         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3932
3933         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3934         strlcat(cachename, "cg/", sizeof(cachename));
3935
3936         // the first pretext is which type of shader to compile as
3937         // (later these will all be bound together as a program object)
3938         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3939         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3940         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3941
3942         // the second pretext is the mode (for example a light source)
3943         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3944         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3945         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3946         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3947         strlcat(cachename, modeinfo->name, sizeof(cachename));
3948
3949         // now add all the permutation pretexts
3950         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3951         {
3952                 if (permutation & (1<<i))
3953                 {
3954                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3955                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3956                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3957                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3958                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3959                 }
3960                 else
3961                 {
3962                         // keep line numbers correct
3963                         vertstrings_list[vertstrings_count++] = "\n";
3964                         geomstrings_list[geomstrings_count++] = "\n";
3965                         fragstrings_list[fragstrings_count++] = "\n";
3966                 }
3967         }
3968
3969         // replace spaces in the cachename with _ characters
3970         for (i = 0;cachename[i];i++)
3971                 if (cachename[i] == ' ')
3972                         cachename[i] = '_';
3973
3974         // now append the shader text itself
3975         vertstrings_list[vertstrings_count++] = vertexstring;
3976         geomstrings_list[geomstrings_count++] = geometrystring;
3977         fragstrings_list[fragstrings_count++] = fragmentstring;
3978
3979         // if any sources were NULL, clear the respective list
3980         if (!vertexstring)
3981                 vertstrings_count = 0;
3982         if (!geometrystring)
3983                 geomstrings_count = 0;
3984         if (!fragmentstring)
3985                 fragstrings_count = 0;
3986
3987         vertstring_length = 0;
3988         for (i = 0;i < vertstrings_count;i++)
3989                 vertstring_length += strlen(vertstrings_list[i]);
3990         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
3991         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
3992                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
3993
3994         geomstring_length = 0;
3995         for (i = 0;i < geomstrings_count;i++)
3996                 geomstring_length += strlen(geomstrings_list[i]);
3997         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
3998         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
3999                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4000
4001         fragstring_length = 0;
4002         for (i = 0;i < fragstrings_count;i++)
4003                 fragstring_length += strlen(fragstrings_list[i]);
4004         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4005         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4006                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4007
4008         CHECKGLERROR
4009         CHECKCGERROR
4010         //vertexProfile = CG_PROFILE_ARBVP1;
4011         //fragmentProfile = CG_PROFILE_ARBFP1;
4012         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4013         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4014         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4015         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4016         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4017         CHECKGLERROR
4018
4019         // try to load the cached shader, or generate one
4020         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4021
4022         // if caching failed, do a dynamic compile for now
4023         CHECKCGERROR
4024         if (vertstring[0] && !p->vprogram)
4025                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4026         CHECKCGERROR
4027         if (fragstring[0] && !p->fprogram)
4028                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4029         CHECKCGERROR
4030
4031         // look up all the uniform variable names we care about, so we don't
4032         // have to look them up every time we set them
4033         if (p->vprogram)
4034         {
4035                 CHECKCGERROR
4036                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4037                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4038                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4039                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4040                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4041                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4042                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4043                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4044                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4045                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4046                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4047                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4048                 CHECKCGERROR
4049         }
4050         if (p->fprogram)
4051         {
4052                 CHECKCGERROR
4053                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4054                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4055                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4056                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4057                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4058                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4059                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4060                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4061                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4062                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4063                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4064                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4065                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4066                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4067                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4068                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4069                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4070                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4071                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4072                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4073                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4074                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4075                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4076                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4077                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4078                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4079                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4080                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4081                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4082                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4083                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4084                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4085                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4086                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4087                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4088                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4089                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4090                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4091                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4092                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4093                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4094                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4095                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4096                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4097                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4098                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4099                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4100                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4101                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4102                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4103                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4104                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4105                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4106                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4107                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4108                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4109                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4110                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4111                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4112                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4113                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4114                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4115                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4116                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4117                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4118                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4119                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4120                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4121                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4122                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4123                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4124                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4125                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4126                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4127                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4128                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4129                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4130                 CHECKCGERROR
4131         }
4132
4133         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4134                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4135         else
4136                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4137
4138         // free the strings
4139         if (vertstring)
4140                 Mem_Free(vertstring);
4141         if (geomstring)
4142                 Mem_Free(geomstring);
4143         if (fragstring)
4144                 Mem_Free(fragstring);
4145         if (vertexstring)
4146                 Mem_Free(vertexstring);
4147         if (geometrystring)
4148                 Mem_Free(geometrystring);
4149         if (fragmentstring)
4150                 Mem_Free(fragmentstring);
4151 }
4152
4153 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4154 {
4155         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4156         CHECKGLERROR
4157         CHECKCGERROR
4158         if (r_cg_permutation != perm)
4159         {
4160                 r_cg_permutation = perm;
4161                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4162                 {
4163                         if (!r_cg_permutation->compiled)
4164                                 R_CG_CompilePermutation(perm, mode, permutation);
4165                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4166                         {
4167                                 // remove features until we find a valid permutation
4168                                 int i;
4169                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4170                                 {
4171                                         // reduce i more quickly whenever it would not remove any bits
4172                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4173                                         if (!(permutation & j))
4174                                                 continue;
4175                                         permutation -= j;
4176                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4177                                         if (!r_cg_permutation->compiled)
4178                                                 R_CG_CompilePermutation(perm, mode, permutation);
4179                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4180                                                 break;
4181                                 }
4182                                 if (i >= SHADERPERMUTATION_COUNT)
4183                                 {
4184                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4185                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4186                                         return; // no bit left to clear, entire mode is broken
4187                                 }
4188                         }
4189                 }
4190                 CHECKGLERROR
4191                 CHECKCGERROR
4192                 if (r_cg_permutation->vprogram)
4193                 {
4194                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4195                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4196                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4197                 }
4198                 else
4199                 {
4200                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4201                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4202                 }
4203                 if (r_cg_permutation->fprogram)
4204                 {
4205                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4206                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4207                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4208                 }
4209                 else
4210                 {
4211                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4212                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4213                 }
4214         }
4215         CHECKCGERROR
4216         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4217         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4218         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4219 }
4220
4221 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4222 {
4223         cgGLSetTextureParameter(param, R_GetTexture(tex));
4224         cgGLEnableTextureParameter(param);
4225 }
4226 #endif
4227
4228 void R_GLSL_Restart_f(void)
4229 {
4230         unsigned int i, limit;
4231         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4232                 Mem_Free(glslshaderstring);
4233         glslshaderstring = NULL;
4234         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4235                 Mem_Free(cgshaderstring);
4236         cgshaderstring = NULL;
4237         switch(vid.renderpath)
4238         {
4239         case RENDERPATH_GL20:
4240                 {
4241                         r_glsl_permutation_t *p;
4242                         r_glsl_permutation = NULL;
4243                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4244                         for (i = 0;i < limit;i++)
4245                         {
4246                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4247                                 {
4248                                         GL_Backend_FreeProgram(p->program);
4249                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4250                                 }
4251                         }
4252                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4253                 }
4254                 break;
4255         case RENDERPATH_CGGL:
4256 #ifdef SUPPORTCG
4257                 {
4258                         r_cg_permutation_t *p;
4259                         r_cg_permutation = NULL;
4260                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4261                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4262                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4263                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4264                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4265                         for (i = 0;i < limit;i++)
4266                         {
4267                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4268                                 {
4269                                         if (p->vprogram)
4270                                                 cgDestroyProgram(p->vprogram);
4271                                         if (p->fprogram)
4272                                                 cgDestroyProgram(p->fprogram);
4273                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4274                                 }
4275                         }
4276                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4277                 }
4278                 break;
4279 #endif
4280         case RENDERPATH_GL13:
4281         case RENDERPATH_GL11:
4282                 break;
4283         }
4284 }
4285
4286 void R_GLSL_DumpShader_f(void)
4287 {
4288         int i;
4289         qfile_t *file;
4290
4291         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4292         if (file)
4293         {
4294                 FS_Print(file, "/* The engine may define the following macros:\n");
4295                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4296                 for (i = 0;i < SHADERMODE_COUNT;i++)
4297                         FS_Print(file, glslshadermodeinfo[i].pretext);
4298                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4299                         FS_Print(file, shaderpermutationinfo[i].pretext);
4300                 FS_Print(file, "*/\n");
4301                 FS_Print(file, builtinshaderstring);
4302                 FS_Close(file);
4303                 Con_Printf("glsl/default.glsl written\n");
4304         }
4305         else
4306                 Con_Printf("failed to write to glsl/default.glsl\n");
4307
4308 #ifdef SUPPORTCG
4309         file = FS_OpenRealFile("cg/default.cg", "w", false);
4310         if (file)
4311         {
4312                 FS_Print(file, "/* The engine may define the following macros:\n");
4313                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4314                 for (i = 0;i < SHADERMODE_COUNT;i++)
4315                         FS_Print(file, cgshadermodeinfo[i].pretext);
4316                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4317                         FS_Print(file, shaderpermutationinfo[i].pretext);
4318                 FS_Print(file, "*/\n");
4319                 FS_Print(file, builtincgshaderstring);
4320                 FS_Close(file);
4321                 Con_Printf("cg/default.cg written\n");
4322         }
4323         else
4324                 Con_Printf("failed to write to cg/default.cg\n");
4325 #endif
4326 }
4327
4328 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4329 {
4330         if (!second)
4331                 texturemode = GL_MODULATE;
4332         switch (vid.renderpath)
4333         {
4334         case RENDERPATH_GL20:
4335                 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))));
4336                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4337                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4338                 break;
4339         case RENDERPATH_CGGL:
4340 #ifdef SUPPORTCG
4341                 CHECKCGERROR
4342                 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))));
4343                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4344                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4345 #endif
4346                 break;
4347         case RENDERPATH_GL13:
4348                 R_Mesh_TexBind(0, first );
4349                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4350                 R_Mesh_TexBind(1, second);
4351                 if (second)
4352                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4353                 break;
4354         case RENDERPATH_GL11:
4355                 R_Mesh_TexBind(0, first );
4356                 break;
4357         }
4358 }
4359
4360 void R_SetupShader_DepthOrShadow(void)
4361 {
4362         switch (vid.renderpath)
4363         {
4364         case RENDERPATH_GL20:
4365                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4366                 break;
4367         case RENDERPATH_CGGL:
4368 #ifdef SUPPORTCG
4369                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4370 #endif
4371                 break;
4372         case RENDERPATH_GL13:
4373                 R_Mesh_TexBind(0, 0);
4374                 R_Mesh_TexBind(1, 0);
4375                 break;
4376         case RENDERPATH_GL11:
4377                 R_Mesh_TexBind(0, 0);
4378                 break;
4379         }
4380 }
4381
4382 void R_SetupShader_ShowDepth(void)
4383 {
4384         switch (vid.renderpath)
4385         {
4386         case RENDERPATH_GL20:
4387                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4388                 break;
4389         case RENDERPATH_CGGL:
4390 #ifdef SUPPORTCG
4391                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4392 #endif
4393                 break;
4394         case RENDERPATH_GL13:
4395                 break;
4396         case RENDERPATH_GL11:
4397                 break;
4398         }
4399 }
4400
4401 extern qboolean r_shadow_usingdeferredprepass;
4402 extern cvar_t r_shadow_deferred_8bitrange;
4403 extern rtexture_t *r_shadow_attenuationgradienttexture;
4404 extern rtexture_t *r_shadow_attenuation2dtexture;
4405 extern rtexture_t *r_shadow_attenuation3dtexture;
4406 extern qboolean r_shadow_usingshadowmaprect;
4407 extern qboolean r_shadow_usingshadowmapcube;
4408 extern qboolean r_shadow_usingshadowmap2d;
4409 extern qboolean r_shadow_usingshadowmaportho;
4410 extern float r_shadow_shadowmap_texturescale[2];
4411 extern float r_shadow_shadowmap_parameters[4];
4412 extern qboolean r_shadow_shadowmapvsdct;
4413 extern qboolean r_shadow_shadowmapsampler;
4414 extern int r_shadow_shadowmappcf;
4415 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4416 extern rtexture_t *r_shadow_shadowmap2dtexture;
4417 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4418 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4419 extern matrix4x4_t r_shadow_shadowmapmatrix;
4420 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4421 extern int r_shadow_prepass_width;
4422 extern int r_shadow_prepass_height;
4423 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4424 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4425 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4426 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4427 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4428 {
4429         // select a permutation of the lighting shader appropriate to this
4430         // combination of texture, entity, light source, and fogging, only use the
4431         // minimum features necessary to avoid wasting rendering time in the
4432         // fragment shader on features that are not being used
4433         unsigned int permutation = 0;
4434         unsigned int mode = 0;
4435         float m16f[16];
4436         if (rsurfacepass == RSURFPASS_BACKGROUND)
4437         {
4438                 // distorted background
4439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4440                         mode = SHADERMODE_WATER;
4441                 else
4442                         mode = SHADERMODE_REFRACTION;
4443                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4444                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4445                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4446                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4447                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4448                 R_Mesh_ColorPointer(NULL, 0, 0);
4449                 GL_AlphaTest(false);
4450                 GL_BlendFunc(GL_ONE, GL_ZERO);
4451         }
4452         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4453         {
4454                 if (r_glsl_offsetmapping.integer)
4455                 {
4456                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4457                         if (r_glsl_offsetmapping_reliefmapping.integer)
4458                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4459                 }
4460                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4461                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4463                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4464                 // normalmap (deferred prepass), may use alpha test on diffuse
4465                 mode = SHADERMODE_DEFERREDGEOMETRY;
4466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4467                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4468                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4469                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4470                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4471                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4472                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4473                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4474                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4475                 else
4476                         R_Mesh_ColorPointer(NULL, 0, 0);
4477                 GL_AlphaTest(false);
4478                 GL_BlendFunc(GL_ONE, GL_ZERO);
4479         }
4480         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4481         {
4482                 if (r_glsl_offsetmapping.integer)
4483                 {
4484                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4485                         if (r_glsl_offsetmapping_reliefmapping.integer)
4486                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4487                 }
4488                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4489                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4490                 // light source
4491                 mode = SHADERMODE_LIGHTSOURCE;
4492                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4493                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4494                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4495                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4496                 if (diffusescale > 0)
4497                         permutation |= SHADERPERMUTATION_DIFFUSE;
4498                 if (specularscale > 0)
4499                 {
4500                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4501                         if (r_shadow_glossexact.integer)
4502                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4503                 }
4504                 if (r_refdef.fogenabled)
4505                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4506                 if (rsurface.texture->colormapping)
4507                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4508                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4509                 {
4510                         if (r_shadow_usingshadowmaprect)
4511                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4512                         if (r_shadow_usingshadowmap2d)
4513                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4514                         if (r_shadow_usingshadowmapcube)
4515                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4516                         else if(r_shadow_shadowmapvsdct)
4517                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4518
4519                         if (r_shadow_shadowmapsampler)
4520                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4521                         if (r_shadow_shadowmappcf > 1)
4522                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4523                         else if (r_shadow_shadowmappcf)
4524                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4525                 }
4526                 if (rsurface.texture->reflectmasktexture)
4527                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4528                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4529                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4530                 {
4531                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4532                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4533                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4534                 }
4535                 else
4536                 {
4537                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4538                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4539                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4540                 }
4541                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4542                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4543                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4544                 else
4545                         R_Mesh_ColorPointer(NULL, 0, 0);
4546                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4547                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4548         }
4549         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4550         {
4551                 if (r_glsl_offsetmapping.integer)
4552                 {
4553                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4554                         if (r_glsl_offsetmapping_reliefmapping.integer)
4555                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4556                 }
4557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4558                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4559                 // unshaded geometry (fullbright or ambient model lighting)
4560                 mode = SHADERMODE_FLATCOLOR;
4561                 ambientscale = diffusescale = specularscale = 0;
4562                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4563                         permutation |= SHADERPERMUTATION_GLOW;
4564                 if (r_refdef.fogenabled)
4565                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4566                 if (rsurface.texture->colormapping)
4567                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4568                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4569                 {
4570                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4571                         if (r_shadow_usingshadowmaprect)
4572                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4573                         if (r_shadow_usingshadowmap2d)
4574                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4575
4576                         if (r_shadow_shadowmapsampler)
4577                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4578                         if (r_shadow_shadowmappcf > 1)
4579                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4580                         else if (r_shadow_shadowmappcf)
4581                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4582                 }
4583                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4584                         permutation |= SHADERPERMUTATION_REFLECTION;
4585                 if (rsurface.texture->reflectmasktexture)
4586                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4587                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4588                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4589                 {
4590                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4591                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4592                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4593                 }
4594                 else
4595                 {
4596                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4597                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4598                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4599                 }
4600                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4601                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4602                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4603                 else
4604                         R_Mesh_ColorPointer(NULL, 0, 0);
4605                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4606                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4607         }
4608         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4609         {
4610                 if (r_glsl_offsetmapping.integer)
4611                 {
4612                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4613                         if (r_glsl_offsetmapping_reliefmapping.integer)
4614                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4615                 }
4616                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4617                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4618                 // directional model lighting
4619                 mode = SHADERMODE_LIGHTDIRECTION;
4620                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4621                         permutation |= SHADERPERMUTATION_GLOW;
4622                 permutation |= SHADERPERMUTATION_DIFFUSE;
4623                 if (specularscale > 0)
4624                 {
4625                         permutation |= SHADERPERMUTATION_SPECULAR;
4626                         if (r_shadow_glossexact.integer)
4627                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4628                 }
4629                 if (r_refdef.fogenabled)
4630                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4631                 if (rsurface.texture->colormapping)
4632                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4633                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4634                 {
4635                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4636                         if (r_shadow_usingshadowmaprect)
4637                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4638                         if (r_shadow_usingshadowmap2d)
4639                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4640
4641                         if (r_shadow_shadowmapsampler)
4642                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4643                         if (r_shadow_shadowmappcf > 1)
4644                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4645                         else if (r_shadow_shadowmappcf)
4646                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4647                 }
4648                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4649                         permutation |= SHADERPERMUTATION_REFLECTION;
4650                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4651                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4652                 if (rsurface.texture->reflectmasktexture)
4653                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4654                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4655                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4656                 {
4657                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4658                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4659                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4660                 }
4661                 else
4662                 {
4663                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4664                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4665                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4666                 }
4667                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4668                 R_Mesh_ColorPointer(NULL, 0, 0);
4669                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4670                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4671         }
4672         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4673         {
4674                 if (r_glsl_offsetmapping.integer)
4675                 {
4676                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4677                         if (r_glsl_offsetmapping_reliefmapping.integer)
4678                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4679                 }
4680                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4681                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4682                 // ambient model lighting
4683                 mode = SHADERMODE_LIGHTDIRECTION;
4684                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4685                         permutation |= SHADERPERMUTATION_GLOW;
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
4730         {
4731                 if (r_glsl_offsetmapping.integer)
4732                 {
4733                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4734                         if (r_glsl_offsetmapping_reliefmapping.integer)
4735                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4736                 }
4737                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4738                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4739                 // lightmapped wall
4740                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4741                         permutation |= SHADERPERMUTATION_GLOW;
4742                 if (r_refdef.fogenabled)
4743                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4744                 if (rsurface.texture->colormapping)
4745                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4746                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4747                 {
4748                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4749                         if (r_shadow_usingshadowmaprect)
4750                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4751                         if (r_shadow_usingshadowmap2d)
4752                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4753
4754                         if (r_shadow_shadowmapsampler)
4755                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4756                         if (r_shadow_shadowmappcf > 1)
4757                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4758                         else if (r_shadow_shadowmappcf)
4759                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4760                 }
4761                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4762                         permutation |= SHADERPERMUTATION_REFLECTION;
4763                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4764                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4765                 if (rsurface.texture->reflectmasktexture)
4766                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4767                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4768                 {
4769                         // deluxemapping (light direction texture)
4770                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4771                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4772                         else
4773                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4774                         permutation |= SHADERPERMUTATION_DIFFUSE;
4775                         if (specularscale > 0)
4776                         {
4777                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4778                                 if (r_shadow_glossexact.integer)
4779                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4780                         }
4781                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4782                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4783                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4784                         else
4785                                 R_Mesh_ColorPointer(NULL, 0, 0);
4786                 }
4787                 else if (r_glsl_deluxemapping.integer >= 2)
4788                 {
4789                         // fake deluxemapping (uniform light direction in tangentspace)
4790                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4791                         permutation |= SHADERPERMUTATION_DIFFUSE;
4792                         if (specularscale > 0)
4793                         {
4794                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4795                                 if (r_shadow_glossexact.integer)
4796                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4797                         }
4798                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4799                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4800                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4801                         else
4802                                 R_Mesh_ColorPointer(NULL, 0, 0);
4803                 }
4804                 else if (rsurface.uselightmaptexture)
4805                 {
4806                         // ordinary lightmapping (q1bsp, q3bsp)
4807                         mode = SHADERMODE_LIGHTMAP;
4808                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4809                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4810                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4811                         else
4812                                 R_Mesh_ColorPointer(NULL, 0, 0);
4813                 }
4814                 else
4815                 {
4816                         // ordinary vertex coloring (q3bsp)
4817                         mode = SHADERMODE_VERTEXCOLOR;
4818                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4819                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4820                 }
4821                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4822                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4823                 {
4824                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4825                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4826                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4827                 }
4828                 else
4829                 {
4830                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4831                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4832                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4833                 }
4834                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4835                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4836         }
4837         switch(vid.renderpath)
4838         {
4839         case RENDERPATH_GL20:
4840                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4841                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4842                 if (mode == SHADERMODE_LIGHTSOURCE)
4843                 {
4844                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4845                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4846                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4847                         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);
4848                         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);
4849                         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);
4850         
4851                         // additive passes are only darkened by fog, not tinted
4852                         if (r_glsl_permutation->loc_FogColor >= 0)
4853                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4854                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4855                 }
4856                 else
4857                 {
4858                         if (mode == SHADERMODE_FLATCOLOR)
4859                         {
4860                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4861                         }
4862                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4863                         {
4864                                 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]);
4865                                 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]);
4866                                 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);
4867                                 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);
4868                                 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);
4869                                 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]);
4870                                 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]);
4871                         }
4872                         else
4873                         {
4874                                 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]);
4875                                 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]);
4876                                 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);
4877                                 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);
4878                                 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);
4879                         }
4880                         // additive passes are only darkened by fog, not tinted
4881                         if (r_glsl_permutation->loc_FogColor >= 0)
4882                         {
4883                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4884                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4885                                 else
4886                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4887                         }
4888                         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);
4889                         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]);
4890                         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]);
4891                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4892                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4893                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4894                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4895                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4896                 }
4897                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4898                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4899                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4900                 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]);
4901                 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]);
4902
4903                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4904                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4905                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4906                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4907                 {
4908                         if (rsurface.texture->pantstexture)
4909                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4910                         else
4911                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4912                 }
4913                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4914                 {
4915                         if (rsurface.texture->shirttexture)
4916                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4917                         else
4918                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4919                 }
4920                 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]);
4921                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4922                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4923                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4924                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4925                 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]);
4926                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4927
4928         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4929         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4930         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4931                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4932                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4933                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4934                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4935                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4936                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4937                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4938                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4939                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4940                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4941                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
4942                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4943                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4944                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4945                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4946                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4947                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4948                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4949                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4950                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4951                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4952                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4953                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
4954                 {
4955                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
4956                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
4957                         if (rsurface.rtlight)
4958                         {
4959                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4960                                 if (r_shadow_usingshadowmapcube)
4961                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4962                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4963                         }
4964                 }
4965                 CHECKGLERROR
4966                 break;
4967         case RENDERPATH_CGGL:
4968 #ifdef SUPPORTCG
4969                 R_SetupShader_SetPermutationCG(mode, permutation);
4970                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
4971                 if (mode == SHADERMODE_LIGHTSOURCE)
4972                 {
4973                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
4974                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4975                 }
4976                 else
4977                 {
4978                         if (mode == SHADERMODE_LIGHTDIRECTION)
4979                         {
4980                                 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
4981                         }
4982                 }
4983                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
4984                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
4985                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
4986                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
4987                 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
4988                 CHECKGLERROR
4989
4990                 if (mode == SHADERMODE_LIGHTSOURCE)
4991                 {
4992                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
4993                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
4994                         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
4995                         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
4996                         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
4997
4998                         // additive passes are only darkened by fog, not tinted
4999                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5000                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5001                 }
5002                 else
5003                 {
5004                         if (mode == SHADERMODE_FLATCOLOR)
5005                         {
5006                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5007                         }
5008                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5009                         {
5010                                 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
5011                                 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
5012                                 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
5013                                 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
5014                                 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
5015                                 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
5016                                 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
5017                         }
5018                         else
5019                         {
5020                                 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
5021                                 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
5022                                 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
5023                                 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
5024                                 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
5025                         }
5026                         // additive passes are only darkened by fog, not tinted
5027                         if (r_cg_permutation->fp_FogColor)
5028                         {
5029                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5030                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5031                                 else
5032                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5033                                 CHECKCGERROR
5034                         }
5035                         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
5036                         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
5037                         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
5038                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5039                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5040                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5041                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5042                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5043                 }
5044                 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
5045                 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
5046                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5047                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5048                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5049                 if (r_cg_permutation->fp_Color_Pants)
5050                 {
5051                         if (rsurface.texture->pantstexture)
5052                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5053                         else
5054                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5055                         CHECKCGERROR
5056                 }
5057                 if (r_cg_permutation->fp_Color_Shirt)
5058                 {
5059                         if (rsurface.texture->shirttexture)
5060                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5061                         else
5062                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5063                         CHECKCGERROR
5064                 }
5065                 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
5066                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5067                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5068                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5069                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5070                 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
5071                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5072
5073         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5074         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5075         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5076                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5077                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5078                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5079                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5080                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5081                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5082                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5083                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5084                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5085                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5086                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5087                 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
5088                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5089                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5090                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5091                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5092                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5093                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5094                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5095                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5096                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5097                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5098                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5099                 {
5100                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5101                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5102                         if (rsurface.rtlight)
5103                         {
5104                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5105                                 if (r_shadow_usingshadowmapcube)
5106                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5107                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5108                         }
5109                 }
5110
5111                 CHECKGLERROR
5112 #endif
5113                 break;
5114         case RENDERPATH_GL13:
5115         case RENDERPATH_GL11:
5116                 break;
5117         }
5118 }
5119
5120 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5121 {
5122         // select a permutation of the lighting shader appropriate to this
5123         // combination of texture, entity, light source, and fogging, only use the
5124         // minimum features necessary to avoid wasting rendering time in the
5125         // fragment shader on features that are not being used
5126         unsigned int permutation = 0;
5127         unsigned int mode = 0;
5128         const float *lightcolorbase = rtlight->currentcolor;
5129         float ambientscale = rtlight->ambientscale;
5130         float diffusescale = rtlight->diffusescale;
5131         float specularscale = rtlight->specularscale;
5132         // this is the location of the light in view space
5133         vec3_t viewlightorigin;
5134         // this transforms from view space (camera) to light space (cubemap)
5135         matrix4x4_t viewtolight;
5136         matrix4x4_t lighttoview;
5137         float viewtolight16f[16];
5138         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5139         // light source
5140         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5141         if (rtlight->currentcubemap != r_texture_whitecube)
5142                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5143         if (diffusescale > 0)
5144                 permutation |= SHADERPERMUTATION_DIFFUSE;
5145         if (specularscale > 0)
5146         {
5147                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5148                 if (r_shadow_glossexact.integer)
5149                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5150         }
5151         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5152         {
5153                 if (r_shadow_usingshadowmaprect)
5154                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5155                 if (r_shadow_usingshadowmap2d)
5156                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5157                 if (r_shadow_usingshadowmapcube)
5158                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5159                 else if(r_shadow_shadowmapvsdct)
5160                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5161
5162                 if (r_shadow_shadowmapsampler)
5163                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5164                 if (r_shadow_shadowmappcf > 1)
5165                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5166                 else if (r_shadow_shadowmappcf)
5167                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5168         }
5169         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5170         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5171         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5172         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5173         switch(vid.renderpath)
5174         {
5175         case RENDERPATH_GL20:
5176                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5177                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5178                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5179                 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);
5180                 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);
5181                 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);
5182                 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]);
5183                 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]);
5184                 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));
5185                 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]);
5186                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5187
5188                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5189                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5190                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5191                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5192                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5193                 if (r_shadow_usingshadowmapcube)
5194                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5195                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5196                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5197                 break;
5198         case RENDERPATH_CGGL:
5199 #ifdef SUPPORTCG
5200                 R_SetupShader_SetPermutationCG(mode, permutation);
5201                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5202                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5203                 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
5204                 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
5205                 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
5206                 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
5207                 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
5208                 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
5209                 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
5210                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5211
5212                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5213                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5214                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5215                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5216                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5217                 if (r_shadow_usingshadowmapcube)
5218                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5219                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5220                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5221 #endif
5222                 break;
5223         case RENDERPATH_GL13:
5224         case RENDERPATH_GL11:
5225                 break;
5226         }
5227 }
5228
5229 #define SKINFRAME_HASH 1024
5230
5231 typedef struct
5232 {
5233         int loadsequence; // incremented each level change
5234         memexpandablearray_t array;
5235         skinframe_t *hash[SKINFRAME_HASH];
5236 }
5237 r_skinframe_t;
5238 r_skinframe_t r_skinframe;
5239
5240 void R_SkinFrame_PrepareForPurge(void)
5241 {
5242         r_skinframe.loadsequence++;
5243         // wrap it without hitting zero
5244         if (r_skinframe.loadsequence >= 200)
5245                 r_skinframe.loadsequence = 1;
5246 }
5247
5248 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5249 {
5250         if (!skinframe)
5251                 return;
5252         // mark the skinframe as used for the purging code
5253         skinframe->loadsequence = r_skinframe.loadsequence;
5254 }
5255
5256 void R_SkinFrame_Purge(void)
5257 {
5258         int i;
5259         skinframe_t *s;
5260         for (i = 0;i < SKINFRAME_HASH;i++)
5261         {
5262                 for (s = r_skinframe.hash[i];s;s = s->next)
5263                 {
5264                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5265                         {
5266                                 if (s->merged == s->base)
5267                                         s->merged = NULL;
5268                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5269                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5270                                 R_PurgeTexture(s->merged);s->merged = NULL;
5271                                 R_PurgeTexture(s->base  );s->base   = NULL;
5272                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5273                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5274                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5275                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5276                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5277                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5278                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5279                                 s->loadsequence = 0;
5280                         }
5281                 }
5282         }
5283 }
5284
5285 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5286         skinframe_t *item;
5287         char basename[MAX_QPATH];
5288
5289         Image_StripImageExtension(name, basename, sizeof(basename));
5290
5291         if( last == NULL ) {
5292                 int hashindex;
5293                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5294                 item = r_skinframe.hash[hashindex];
5295         } else {
5296                 item = last->next;
5297         }
5298
5299         // linearly search through the hash bucket
5300         for( ; item ; item = item->next ) {
5301                 if( !strcmp( item->basename, basename ) ) {
5302                         return item;
5303                 }
5304         }
5305         return NULL;
5306 }
5307
5308 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5309 {
5310         skinframe_t *item;
5311         int hashindex;
5312         char basename[MAX_QPATH];
5313
5314         Image_StripImageExtension(name, basename, sizeof(basename));
5315
5316         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5317         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5318                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5319                         break;
5320
5321         if (!item) {
5322                 rtexture_t *dyntexture;
5323                 // check whether its a dynamic texture
5324                 dyntexture = CL_GetDynTexture( basename );
5325                 if (!add && !dyntexture)
5326                         return NULL;
5327                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5328                 memset(item, 0, sizeof(*item));
5329                 strlcpy(item->basename, basename, sizeof(item->basename));
5330                 item->base = dyntexture; // either NULL or dyntexture handle
5331                 item->textureflags = textureflags;
5332                 item->comparewidth = comparewidth;
5333                 item->compareheight = compareheight;
5334                 item->comparecrc = comparecrc;
5335                 item->next = r_skinframe.hash[hashindex];
5336                 r_skinframe.hash[hashindex] = item;
5337         }
5338         else if( item->base == NULL )
5339         {
5340                 rtexture_t *dyntexture;
5341                 // check whether its a dynamic texture
5342                 // 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]
5343                 dyntexture = CL_GetDynTexture( basename );
5344                 item->base = dyntexture; // either NULL or dyntexture handle
5345         }
5346
5347         R_SkinFrame_MarkUsed(item);
5348         return item;
5349 }
5350
5351 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5352         { \
5353                 unsigned long long avgcolor[5], wsum; \
5354                 int pix, comp, w; \
5355                 avgcolor[0] = 0; \
5356                 avgcolor[1] = 0; \
5357                 avgcolor[2] = 0; \
5358                 avgcolor[3] = 0; \
5359                 avgcolor[4] = 0; \
5360                 wsum = 0; \
5361                 for(pix = 0; pix < cnt; ++pix) \
5362                 { \
5363                         w = 0; \
5364                         for(comp = 0; comp < 3; ++comp) \
5365                                 w += getpixel; \
5366                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5367                         { \
5368                                 ++wsum; \
5369                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5370                                 w = getpixel; \
5371                                 for(comp = 0; comp < 3; ++comp) \
5372                                         avgcolor[comp] += getpixel * w; \
5373                                 avgcolor[3] += w; \
5374                         } \
5375                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5376                         avgcolor[4] += getpixel; \
5377                 } \
5378                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5379                         avgcolor[3] = 1; \
5380                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5381                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5382                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5383                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5384         }
5385
5386 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5387 {
5388         int j;
5389         unsigned char *pixels;
5390         unsigned char *bumppixels;
5391         unsigned char *basepixels = NULL;
5392         int basepixels_width = 0;
5393         int basepixels_height = 0;
5394         skinframe_t *skinframe;
5395         rtexture_t *ddsbase = NULL;
5396         qboolean ddshasalpha = false;
5397         float ddsavgcolor[4];
5398         char basename[MAX_QPATH];
5399
5400         if (cls.state == ca_dedicated)
5401                 return NULL;
5402
5403         // return an existing skinframe if already loaded
5404         // if loading of the first image fails, don't make a new skinframe as it
5405         // would cause all future lookups of this to be missing
5406         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5407         if (skinframe && skinframe->base)
5408                 return skinframe;
5409
5410         Image_StripImageExtension(name, basename, sizeof(basename));
5411
5412         // check for DDS texture file first
5413         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5414         {
5415                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5416                 if (basepixels == NULL)
5417                         return NULL;
5418         }
5419
5420         if (developer_loading.integer)
5421                 Con_Printf("loading skin \"%s\"\n", name);
5422
5423         // we've got some pixels to store, so really allocate this new texture now
5424         if (!skinframe)
5425                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5426         skinframe->stain = NULL;
5427         skinframe->merged = NULL;
5428         skinframe->base = NULL;
5429         skinframe->pants = NULL;
5430         skinframe->shirt = NULL;
5431         skinframe->nmap = NULL;
5432         skinframe->gloss = NULL;
5433         skinframe->glow = NULL;
5434         skinframe->fog = NULL;
5435         skinframe->reflect = NULL;
5436         skinframe->hasalpha = false;
5437
5438         if (ddsbase)
5439         {
5440                 skinframe->base = ddsbase;
5441                 skinframe->hasalpha = ddshasalpha;
5442                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5443                 if (r_loadfog && skinframe->hasalpha)
5444                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5445                 //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]);
5446         }
5447         else
5448         {
5449                 basepixels_width = image_width;
5450                 basepixels_height = image_height;
5451                 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);
5452                 if (textureflags & TEXF_ALPHA)
5453                 {
5454                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5455                         {
5456                                 if (basepixels[j] < 255)
5457                                 {
5458                                         skinframe->hasalpha = true;
5459                                         break;
5460                                 }
5461                         }
5462                         if (r_loadfog && skinframe->hasalpha)
5463                         {
5464                                 // has transparent pixels
5465                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5466                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5467                                 {
5468                                         pixels[j+0] = 255;
5469                                         pixels[j+1] = 255;
5470                                         pixels[j+2] = 255;
5471                                         pixels[j+3] = basepixels[j+3];
5472                                 }
5473                                 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);
5474                                 Mem_Free(pixels);
5475                         }
5476                 }
5477                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5478                 //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]);
5479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5480                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5482                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5483         }
5484
5485         if (r_loaddds)
5486         {
5487                 if (r_loadnormalmap)
5488                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5489                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5490                 if (r_loadgloss)
5491                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5492                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5493                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5494                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5495         }
5496
5497         // _norm is the name used by tenebrae and has been adopted as standard
5498         if (r_loadnormalmap && skinframe->nmap == NULL)
5499         {
5500                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5501                 {
5502                         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);
5503                         Mem_Free(pixels);
5504                         pixels = NULL;
5505                 }
5506                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5507                 {
5508                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5509                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5510                         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);
5511                         Mem_Free(pixels);
5512                         Mem_Free(bumppixels);
5513                 }
5514                 else if (r_shadow_bumpscale_basetexture.value > 0)
5515                 {
5516                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5517                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5518                         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);
5519                         Mem_Free(pixels);
5520                 }
5521                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5522                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5523         }
5524
5525         // _luma is supported only for tenebrae compatibility
5526         // _glow is the preferred name
5527         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))))
5528         {
5529                 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);
5530                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5531                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5532                 Mem_Free(pixels);pixels = NULL;
5533         }
5534
5535         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5536         {
5537                 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);
5538                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5539                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5540                 Mem_Free(pixels);
5541                 pixels = NULL;
5542         }
5543
5544         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5545         {
5546                 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);
5547                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5548                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5549                 Mem_Free(pixels);
5550                 pixels = NULL;
5551         }
5552
5553         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5554         {
5555                 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);
5556                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5557                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5558                 Mem_Free(pixels);
5559                 pixels = NULL;
5560         }
5561
5562         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5563         {
5564                 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);
5565                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5566                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5567                 Mem_Free(pixels);
5568                 pixels = NULL;
5569         }
5570
5571         if (basepixels)
5572                 Mem_Free(basepixels);
5573
5574         return skinframe;
5575 }
5576
5577 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5578 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5579 {
5580         int i;
5581         unsigned char *temp1, *temp2;
5582         skinframe_t *skinframe;
5583
5584         if (cls.state == ca_dedicated)
5585                 return NULL;
5586
5587         // if already loaded just return it, otherwise make a new skinframe
5588         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5589         if (skinframe && skinframe->base)
5590                 return skinframe;
5591
5592         skinframe->stain = NULL;
5593         skinframe->merged = NULL;
5594         skinframe->base = NULL;
5595         skinframe->pants = NULL;
5596         skinframe->shirt = NULL;
5597         skinframe->nmap = NULL;
5598         skinframe->gloss = NULL;
5599         skinframe->glow = NULL;
5600         skinframe->fog = NULL;
5601         skinframe->reflect = NULL;
5602         skinframe->hasalpha = false;
5603
5604         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5605         if (!skindata)
5606                 return NULL;
5607
5608         if (developer_loading.integer)
5609                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5610
5611         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5612         {
5613                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5614                 temp2 = temp1 + width * height * 4;
5615                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5616                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5617                 Mem_Free(temp1);
5618         }
5619         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5620         if (textureflags & TEXF_ALPHA)
5621         {
5622                 for (i = 3;i < width * height * 4;i += 4)
5623                 {
5624                         if (skindata[i] < 255)
5625                         {
5626                                 skinframe->hasalpha = true;
5627                                 break;
5628                         }
5629                 }
5630                 if (r_loadfog && skinframe->hasalpha)
5631                 {
5632                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5633                         memcpy(fogpixels, skindata, width * height * 4);
5634                         for (i = 0;i < width * height * 4;i += 4)
5635                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5636                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5637                         Mem_Free(fogpixels);
5638                 }
5639         }
5640
5641         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5642         //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]);
5643
5644         return skinframe;
5645 }
5646
5647 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5648 {
5649         int i;
5650         int featuresmask;
5651         skinframe_t *skinframe;
5652
5653         if (cls.state == ca_dedicated)
5654                 return NULL;
5655
5656         // if already loaded just return it, otherwise make a new skinframe
5657         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5658         if (skinframe && skinframe->base)
5659                 return skinframe;
5660
5661         skinframe->stain = NULL;
5662         skinframe->merged = NULL;
5663         skinframe->base = NULL;
5664         skinframe->pants = NULL;
5665         skinframe->shirt = NULL;
5666         skinframe->nmap = NULL;
5667         skinframe->gloss = NULL;
5668         skinframe->glow = NULL;
5669         skinframe->fog = NULL;
5670         skinframe->reflect = NULL;
5671         skinframe->hasalpha = false;
5672
5673         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5674         if (!skindata)
5675                 return NULL;
5676
5677         if (developer_loading.integer)
5678                 Con_Printf("loading quake skin \"%s\"\n", name);
5679
5680         // 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)
5681         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5682         memcpy(skinframe->qpixels, skindata, width*height);
5683         skinframe->qwidth = width;
5684         skinframe->qheight = height;
5685
5686         featuresmask = 0;
5687         for (i = 0;i < width * height;i++)
5688                 featuresmask |= palette_featureflags[skindata[i]];
5689
5690         skinframe->hasalpha = false;
5691         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5692         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5693         skinframe->qgeneratemerged = true;
5694         skinframe->qgeneratebase = skinframe->qhascolormapping;
5695         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5696
5697         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5698         //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]);
5699
5700         return skinframe;
5701 }
5702
5703 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5704 {
5705         int width;
5706         int height;
5707         unsigned char *skindata;
5708
5709         if (!skinframe->qpixels)
5710                 return;
5711
5712         if (!skinframe->qhascolormapping)
5713                 colormapped = false;
5714
5715         if (colormapped)
5716         {
5717                 if (!skinframe->qgeneratebase)
5718                         return;
5719         }
5720         else
5721         {
5722                 if (!skinframe->qgeneratemerged)
5723                         return;
5724         }
5725
5726         width = skinframe->qwidth;
5727         height = skinframe->qheight;
5728         skindata = skinframe->qpixels;
5729
5730         if (skinframe->qgeneratenmap)
5731         {
5732                 unsigned char *temp1, *temp2;
5733                 skinframe->qgeneratenmap = false;
5734                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5735                 temp2 = temp1 + width * height * 4;
5736                 // use either a custom palette or the quake palette
5737                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5738                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5739                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5740                 Mem_Free(temp1);
5741         }
5742
5743         if (skinframe->qgenerateglow)
5744         {
5745                 skinframe->qgenerateglow = false;
5746                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5747         }
5748
5749         if (colormapped)
5750         {
5751                 skinframe->qgeneratebase = false;
5752                 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);
5753                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5754                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5755         }
5756         else
5757         {
5758                 skinframe->qgeneratemerged = false;
5759                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5760         }
5761
5762         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5763         {
5764                 Mem_Free(skinframe->qpixels);
5765                 skinframe->qpixels = NULL;
5766         }
5767 }
5768
5769 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)
5770 {
5771         int i;
5772         skinframe_t *skinframe;
5773
5774         if (cls.state == ca_dedicated)
5775                 return NULL;
5776
5777         // if already loaded just return it, otherwise make a new skinframe
5778         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5779         if (skinframe && skinframe->base)
5780                 return skinframe;
5781
5782         skinframe->stain = NULL;
5783         skinframe->merged = NULL;
5784         skinframe->base = NULL;
5785         skinframe->pants = NULL;
5786         skinframe->shirt = NULL;
5787         skinframe->nmap = NULL;
5788         skinframe->gloss = NULL;
5789         skinframe->glow = NULL;
5790         skinframe->fog = NULL;
5791         skinframe->reflect = NULL;
5792         skinframe->hasalpha = false;
5793
5794         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5795         if (!skindata)
5796                 return NULL;
5797
5798         if (developer_loading.integer)
5799                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5800
5801         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5802         if (textureflags & TEXF_ALPHA)
5803         {
5804                 for (i = 0;i < width * height;i++)
5805                 {
5806                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5807                         {
5808                                 skinframe->hasalpha = true;
5809                                 break;
5810                         }
5811                 }
5812                 if (r_loadfog && skinframe->hasalpha)
5813                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5814         }
5815
5816         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5817         //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]);
5818
5819         return skinframe;
5820 }
5821
5822 skinframe_t *R_SkinFrame_LoadMissing(void)
5823 {
5824         skinframe_t *skinframe;
5825
5826         if (cls.state == ca_dedicated)
5827                 return NULL;
5828
5829         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5830         skinframe->stain = NULL;
5831         skinframe->merged = NULL;
5832         skinframe->base = NULL;
5833         skinframe->pants = NULL;
5834         skinframe->shirt = NULL;
5835         skinframe->nmap = NULL;
5836         skinframe->gloss = NULL;
5837         skinframe->glow = NULL;
5838         skinframe->fog = NULL;
5839         skinframe->reflect = NULL;
5840         skinframe->hasalpha = false;
5841
5842         skinframe->avgcolor[0] = rand() / RAND_MAX;
5843         skinframe->avgcolor[1] = rand() / RAND_MAX;
5844         skinframe->avgcolor[2] = rand() / RAND_MAX;
5845         skinframe->avgcolor[3] = 1;
5846
5847         return skinframe;
5848 }
5849
5850 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5851 typedef struct suffixinfo_s
5852 {
5853         char *suffix;
5854         qboolean flipx, flipy, flipdiagonal;
5855 }
5856 suffixinfo_t;
5857 static suffixinfo_t suffix[3][6] =
5858 {
5859         {
5860                 {"px",   false, false, false},
5861                 {"nx",   false, false, false},
5862                 {"py",   false, false, false},
5863                 {"ny",   false, false, false},
5864                 {"pz",   false, false, false},
5865                 {"nz",   false, false, false}
5866         },
5867         {
5868                 {"posx", false, false, false},
5869                 {"negx", false, false, false},
5870                 {"posy", false, false, false},
5871                 {"negy", false, false, false},
5872                 {"posz", false, false, false},
5873                 {"negz", false, false, false}
5874         },
5875         {
5876                 {"rt",    true, false,  true},
5877                 {"lf",   false,  true,  true},
5878                 {"ft",    true,  true, false},
5879                 {"bk",   false, false, false},
5880                 {"up",    true, false,  true},
5881                 {"dn",    true, false,  true}
5882         }
5883 };
5884
5885 static int componentorder[4] = {0, 1, 2, 3};
5886
5887 rtexture_t *R_LoadCubemap(const char *basename)
5888 {
5889         int i, j, cubemapsize;
5890         unsigned char *cubemappixels, *image_buffer;
5891         rtexture_t *cubemaptexture;
5892         char name[256];
5893         // must start 0 so the first loadimagepixels has no requested width/height
5894         cubemapsize = 0;
5895         cubemappixels = NULL;
5896         cubemaptexture = NULL;
5897         // keep trying different suffix groups (posx, px, rt) until one loads
5898         for (j = 0;j < 3 && !cubemappixels;j++)
5899         {
5900                 // load the 6 images in the suffix group
5901                 for (i = 0;i < 6;i++)
5902                 {
5903                         // generate an image name based on the base and and suffix
5904                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5905                         // load it
5906                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5907                         {
5908                                 // an image loaded, make sure width and height are equal
5909                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5910                                 {
5911                                         // if this is the first image to load successfully, allocate the cubemap memory
5912                                         if (!cubemappixels && image_width >= 1)
5913                                         {
5914                                                 cubemapsize = image_width;
5915                                                 // note this clears to black, so unavailable sides are black
5916                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5917                                         }
5918                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5919                                         if (cubemappixels)
5920                                                 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);
5921                                 }
5922                                 else
5923                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5924                                 // free the image
5925                                 Mem_Free(image_buffer);
5926                         }
5927                 }
5928         }
5929         // if a cubemap loaded, upload it
5930         if (cubemappixels)
5931         {
5932                 if (developer_loading.integer)
5933                         Con_Printf("loading cubemap \"%s\"\n", basename);
5934
5935                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5936                 Mem_Free(cubemappixels);
5937         }
5938         else
5939         {
5940                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5941                 if (developer_loading.integer)
5942                 {
5943                         Con_Printf("(tried tried images ");
5944                         for (j = 0;j < 3;j++)
5945                                 for (i = 0;i < 6;i++)
5946                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5947                         Con_Print(" and was unable to find any of them).\n");
5948                 }
5949         }
5950         return cubemaptexture;
5951 }
5952
5953 rtexture_t *R_GetCubemap(const char *basename)
5954 {
5955         int i;
5956         for (i = 0;i < r_texture_numcubemaps;i++)
5957                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5958                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
5959         if (i >= MAX_CUBEMAPS)
5960                 return r_texture_whitecube;
5961         r_texture_numcubemaps++;
5962         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
5963         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
5964         return r_texture_cubemaps[i].texture;
5965 }
5966
5967 void R_FreeCubemaps(void)
5968 {
5969         int i;
5970         for (i = 0;i < r_texture_numcubemaps;i++)
5971         {
5972                 if (developer_loading.integer)
5973                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
5974                 if (r_texture_cubemaps[i].texture)
5975                         R_FreeTexture(r_texture_cubemaps[i].texture);
5976         }
5977         r_texture_numcubemaps = 0;
5978 }
5979
5980 void R_Main_FreeViewCache(void)
5981 {
5982         if (r_refdef.viewcache.entityvisible)
5983                 Mem_Free(r_refdef.viewcache.entityvisible);
5984         if (r_refdef.viewcache.world_pvsbits)
5985                 Mem_Free(r_refdef.viewcache.world_pvsbits);
5986         if (r_refdef.viewcache.world_leafvisible)
5987                 Mem_Free(r_refdef.viewcache.world_leafvisible);
5988         if (r_refdef.viewcache.world_surfacevisible)
5989                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
5990         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
5991 }
5992
5993 void R_Main_ResizeViewCache(void)
5994 {
5995         int numentities = r_refdef.scene.numentities;
5996         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
5997         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
5998         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
5999         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6000         if (r_refdef.viewcache.maxentities < numentities)
6001         {
6002                 r_refdef.viewcache.maxentities = numentities;
6003                 if (r_refdef.viewcache.entityvisible)
6004                         Mem_Free(r_refdef.viewcache.entityvisible);
6005                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6006         }
6007         if (r_refdef.viewcache.world_numclusters != numclusters)
6008         {
6009                 r_refdef.viewcache.world_numclusters = numclusters;
6010                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6011                 if (r_refdef.viewcache.world_pvsbits)
6012                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6013                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6014         }
6015         if (r_refdef.viewcache.world_numleafs != numleafs)
6016         {
6017                 r_refdef.viewcache.world_numleafs = numleafs;
6018                 if (r_refdef.viewcache.world_leafvisible)
6019                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6020                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6021         }
6022         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6023         {
6024                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6025                 if (r_refdef.viewcache.world_surfacevisible)
6026                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6027                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6028         }
6029 }
6030
6031 extern rtexture_t *loadingscreentexture;
6032 void gl_main_start(void)
6033 {
6034         loadingscreentexture = NULL;
6035         r_texture_blanknormalmap = NULL;
6036         r_texture_white = NULL;
6037         r_texture_grey128 = NULL;
6038         r_texture_black = NULL;
6039         r_texture_whitecube = NULL;
6040         r_texture_normalizationcube = NULL;
6041         r_texture_fogattenuation = NULL;
6042         r_texture_gammaramps = NULL;
6043         r_texture_numcubemaps = 0;
6044
6045         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6046         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6047
6048         switch(vid.renderpath)
6049         {
6050         case RENDERPATH_GL20:
6051         case RENDERPATH_CGGL:
6052                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6053                 Cvar_SetValueQuick(&gl_combine, 1);
6054                 Cvar_SetValueQuick(&r_glsl, 1);
6055                 r_loadnormalmap = true;
6056                 r_loadgloss = true;
6057                 r_loadfog = false;
6058                 break;
6059         case RENDERPATH_GL13:
6060                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6061                 Cvar_SetValueQuick(&gl_combine, 1);
6062                 Cvar_SetValueQuick(&r_glsl, 0);
6063                 r_loadnormalmap = false;
6064                 r_loadgloss = false;
6065                 r_loadfog = true;
6066                 break;
6067         case RENDERPATH_GL11:
6068                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6069                 Cvar_SetValueQuick(&gl_combine, 0);
6070                 Cvar_SetValueQuick(&r_glsl, 0);
6071                 r_loadnormalmap = false;
6072                 r_loadgloss = false;
6073                 r_loadfog = true;
6074                 break;
6075         }
6076
6077         R_AnimCache_Free();
6078         R_FrameData_Reset();
6079
6080         r_numqueries = 0;
6081         r_maxqueries = 0;
6082         memset(r_queries, 0, sizeof(r_queries));
6083
6084         r_qwskincache = NULL;
6085         r_qwskincache_size = 0;
6086
6087         // set up r_skinframe loading system for textures
6088         memset(&r_skinframe, 0, sizeof(r_skinframe));
6089         r_skinframe.loadsequence = 1;
6090         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6091
6092         r_main_texturepool = R_AllocTexturePool();
6093         R_BuildBlankTextures();
6094         R_BuildNoTexture();
6095         if (vid.support.arb_texture_cube_map)
6096         {
6097                 R_BuildWhiteCube();
6098                 R_BuildNormalizationCube();
6099         }
6100         r_texture_fogattenuation = NULL;
6101         r_texture_gammaramps = NULL;
6102         //r_texture_fogintensity = NULL;
6103         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6104         memset(&r_waterstate, 0, sizeof(r_waterstate));
6105         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6106         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6107         glslshaderstring = NULL;
6108 #ifdef SUPPORTCG
6109         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6110         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6111         cgshaderstring = NULL;
6112 #endif
6113         memset(&r_svbsp, 0, sizeof (r_svbsp));
6114
6115         r_refdef.fogmasktable_density = 0;
6116 }
6117
6118 void gl_main_shutdown(void)
6119 {
6120         R_AnimCache_Free();
6121         R_FrameData_Reset();
6122
6123         R_Main_FreeViewCache();
6124
6125         if (r_maxqueries)
6126                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6127
6128         r_numqueries = 0;
6129         r_maxqueries = 0;
6130         memset(r_queries, 0, sizeof(r_queries));
6131
6132         r_qwskincache = NULL;
6133         r_qwskincache_size = 0;
6134
6135         // clear out the r_skinframe state
6136         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6137         memset(&r_skinframe, 0, sizeof(r_skinframe));
6138
6139         if (r_svbsp.nodes)
6140                 Mem_Free(r_svbsp.nodes);
6141         memset(&r_svbsp, 0, sizeof (r_svbsp));
6142         R_FreeTexturePool(&r_main_texturepool);
6143         loadingscreentexture = NULL;
6144         r_texture_blanknormalmap = NULL;
6145         r_texture_white = NULL;
6146         r_texture_grey128 = NULL;
6147         r_texture_black = NULL;
6148         r_texture_whitecube = NULL;
6149         r_texture_normalizationcube = NULL;
6150         r_texture_fogattenuation = NULL;
6151         r_texture_gammaramps = NULL;
6152         r_texture_numcubemaps = 0;
6153         //r_texture_fogintensity = NULL;
6154         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6155         memset(&r_waterstate, 0, sizeof(r_waterstate));
6156         R_GLSL_Restart_f();
6157 }
6158
6159 extern void CL_ParseEntityLump(char *entitystring);
6160 void gl_main_newmap(void)
6161 {
6162         // FIXME: move this code to client
6163         int l;
6164         char *entities, entname[MAX_QPATH];
6165         if (r_qwskincache)
6166                 Mem_Free(r_qwskincache);
6167         r_qwskincache = NULL;
6168         r_qwskincache_size = 0;
6169         if (cl.worldmodel)
6170         {
6171                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6172                 l = (int)strlen(entname) - 4;
6173                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6174                 {
6175                         memcpy(entname + l, ".ent", 5);
6176                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6177                         {
6178                                 CL_ParseEntityLump(entities);
6179                                 Mem_Free(entities);
6180                                 return;
6181                         }
6182                 }
6183                 if (cl.worldmodel->brush.entities)
6184                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6185         }
6186         R_Main_FreeViewCache();
6187
6188         R_FrameData_Reset();
6189 }
6190
6191 void GL_Main_Init(void)
6192 {
6193         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6194
6195         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6196         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6197         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6198         if (gamemode == GAME_NEHAHRA)
6199         {
6200                 Cvar_RegisterVariable (&gl_fogenable);
6201                 Cvar_RegisterVariable (&gl_fogdensity);
6202                 Cvar_RegisterVariable (&gl_fogred);
6203                 Cvar_RegisterVariable (&gl_foggreen);
6204                 Cvar_RegisterVariable (&gl_fogblue);
6205                 Cvar_RegisterVariable (&gl_fogstart);
6206                 Cvar_RegisterVariable (&gl_fogend);
6207                 Cvar_RegisterVariable (&gl_skyclip);
6208         }
6209         Cvar_RegisterVariable(&r_motionblur);
6210         Cvar_RegisterVariable(&r_motionblur_maxblur);
6211         Cvar_RegisterVariable(&r_motionblur_bmin);
6212         Cvar_RegisterVariable(&r_motionblur_vmin);
6213         Cvar_RegisterVariable(&r_motionblur_vmax);
6214         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6215         Cvar_RegisterVariable(&r_motionblur_randomize);
6216         Cvar_RegisterVariable(&r_damageblur);
6217         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6218         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6219         Cvar_RegisterVariable(&r_equalize_entities_by);
6220         Cvar_RegisterVariable(&r_equalize_entities_to);
6221         Cvar_RegisterVariable(&r_depthfirst);
6222         Cvar_RegisterVariable(&r_useinfinitefarclip);
6223         Cvar_RegisterVariable(&r_farclip_base);
6224         Cvar_RegisterVariable(&r_farclip_world);
6225         Cvar_RegisterVariable(&r_nearclip);
6226         Cvar_RegisterVariable(&r_showbboxes);
6227         Cvar_RegisterVariable(&r_showsurfaces);
6228         Cvar_RegisterVariable(&r_showtris);
6229         Cvar_RegisterVariable(&r_shownormals);
6230         Cvar_RegisterVariable(&r_showlighting);
6231         Cvar_RegisterVariable(&r_showshadowvolumes);
6232         Cvar_RegisterVariable(&r_showcollisionbrushes);
6233         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6234         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6235         Cvar_RegisterVariable(&r_showdisabledepthtest);
6236         Cvar_RegisterVariable(&r_drawportals);
6237         Cvar_RegisterVariable(&r_drawentities);
6238         Cvar_RegisterVariable(&r_cullentities_trace);
6239         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6240         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6241         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6242         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6243         Cvar_RegisterVariable(&r_drawviewmodel);
6244         Cvar_RegisterVariable(&r_speeds);
6245         Cvar_RegisterVariable(&r_fullbrights);
6246         Cvar_RegisterVariable(&r_wateralpha);
6247         Cvar_RegisterVariable(&r_dynamic);
6248         Cvar_RegisterVariable(&r_fullbright);
6249         Cvar_RegisterVariable(&r_shadows);
6250         Cvar_RegisterVariable(&r_shadows_darken);
6251         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6252         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6253         Cvar_RegisterVariable(&r_shadows_throwdistance);
6254         Cvar_RegisterVariable(&r_shadows_throwdirection);
6255         Cvar_RegisterVariable(&r_shadows_focus);
6256         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6257         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6258         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6259         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6260         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6261         Cvar_RegisterVariable(&r_fog_exp2);
6262         Cvar_RegisterVariable(&r_drawfog);
6263         Cvar_RegisterVariable(&r_transparentdepthmasking);
6264         Cvar_RegisterVariable(&r_texture_dds_load);
6265         Cvar_RegisterVariable(&r_texture_dds_save);
6266         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6267         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6268         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6269         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6270         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6271         Cvar_RegisterVariable(&r_textureunits);
6272         Cvar_RegisterVariable(&gl_combine);
6273         Cvar_RegisterVariable(&r_glsl);
6274         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6275         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6276         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6277         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6278         Cvar_RegisterVariable(&r_glsl_postprocess);
6279         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6280         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6281         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6282         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6283         Cvar_RegisterVariable(&r_water);
6284         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6285         Cvar_RegisterVariable(&r_water_clippingplanebias);
6286         Cvar_RegisterVariable(&r_water_refractdistort);
6287         Cvar_RegisterVariable(&r_water_reflectdistort);
6288         Cvar_RegisterVariable(&r_lerpsprites);
6289         Cvar_RegisterVariable(&r_lerpmodels);
6290         Cvar_RegisterVariable(&r_lerplightstyles);
6291         Cvar_RegisterVariable(&r_waterscroll);
6292         Cvar_RegisterVariable(&r_bloom);
6293         Cvar_RegisterVariable(&r_bloom_colorscale);
6294         Cvar_RegisterVariable(&r_bloom_brighten);
6295         Cvar_RegisterVariable(&r_bloom_blur);
6296         Cvar_RegisterVariable(&r_bloom_resolution);
6297         Cvar_RegisterVariable(&r_bloom_colorexponent);
6298         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6299         Cvar_RegisterVariable(&r_hdr);
6300         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6301         Cvar_RegisterVariable(&r_hdr_glowintensity);
6302         Cvar_RegisterVariable(&r_hdr_range);
6303         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6304         Cvar_RegisterVariable(&developer_texturelogging);
6305         Cvar_RegisterVariable(&gl_lightmaps);
6306         Cvar_RegisterVariable(&r_test);
6307         Cvar_RegisterVariable(&r_batchmode);
6308         Cvar_RegisterVariable(&r_glsl_saturation);
6309         Cvar_RegisterVariable(&r_framedatasize);
6310         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6311                 Cvar_SetValue("r_fullbrights", 0);
6312         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6313
6314         Cvar_RegisterVariable(&r_track_sprites);
6315         Cvar_RegisterVariable(&r_track_sprites_flags);
6316         Cvar_RegisterVariable(&r_track_sprites_scalew);
6317         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6318         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6319         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6320 }
6321
6322 extern void R_Textures_Init(void);
6323 extern void GL_Draw_Init(void);
6324 extern void GL_Main_Init(void);
6325 extern void R_Shadow_Init(void);
6326 extern void R_Sky_Init(void);
6327 extern void GL_Surf_Init(void);
6328 extern void R_Particles_Init(void);
6329 extern void R_Explosion_Init(void);
6330 extern void gl_backend_init(void);
6331 extern void Sbar_Init(void);
6332 extern void R_LightningBeams_Init(void);
6333 extern void Mod_RenderInit(void);
6334 extern void Font_Init(void);
6335
6336 void Render_Init(void)
6337 {
6338         gl_backend_init();
6339         R_Textures_Init();
6340         GL_Main_Init();
6341         Font_Init();
6342         GL_Draw_Init();
6343         R_Shadow_Init();
6344         R_Sky_Init();
6345         GL_Surf_Init();
6346         Sbar_Init();
6347         R_Particles_Init();
6348         R_Explosion_Init();
6349         R_LightningBeams_Init();
6350         Mod_RenderInit();
6351 }
6352
6353 /*
6354 ===============
6355 GL_Init
6356 ===============
6357 */
6358 extern char *ENGINE_EXTENSIONS;
6359 void GL_Init (void)
6360 {
6361         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6362         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6363         gl_version = (const char *)qglGetString(GL_VERSION);
6364         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6365
6366         if (!gl_extensions)
6367                 gl_extensions = "";
6368         if (!gl_platformextensions)
6369                 gl_platformextensions = "";
6370
6371         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6372         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6373         Con_Printf("GL_VERSION: %s\n", gl_version);
6374         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6375         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6376
6377         VID_CheckExtensions();
6378
6379         // LordHavoc: report supported extensions
6380         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6381
6382         // clear to black (loading plaque will be seen over this)
6383         CHECKGLERROR
6384         qglClearColor(0,0,0,1);CHECKGLERROR
6385         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6386 }
6387
6388 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6389 {
6390         int i;
6391         mplane_t *p;
6392         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6393         {
6394                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6395                 if (i == 4)
6396                         continue;
6397                 p = r_refdef.view.frustum + i;
6398                 switch(p->signbits)
6399                 {
6400                 default:
6401                 case 0:
6402                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6403                                 return true;
6404                         break;
6405                 case 1:
6406                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6407                                 return true;
6408                         break;
6409                 case 2:
6410                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6411                                 return true;
6412                         break;
6413                 case 3:
6414                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6415                                 return true;
6416                         break;
6417                 case 4:
6418                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6419                                 return true;
6420                         break;
6421                 case 5:
6422                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6423                                 return true;
6424                         break;
6425                 case 6:
6426                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6427                                 return true;
6428                         break;
6429                 case 7:
6430                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6431                                 return true;
6432                         break;
6433                 }
6434         }
6435         return false;
6436 }
6437
6438 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6439 {
6440         int i;
6441         const mplane_t *p;
6442         for (i = 0;i < numplanes;i++)
6443         {
6444                 p = planes + i;
6445                 switch(p->signbits)
6446                 {
6447                 default:
6448                 case 0:
6449                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6450                                 return true;
6451                         break;
6452                 case 1:
6453                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6454                                 return true;
6455                         break;
6456                 case 2:
6457                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6458                                 return true;
6459                         break;
6460                 case 3:
6461                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6462                                 return true;
6463                         break;
6464                 case 4:
6465                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6466                                 return true;
6467                         break;
6468                 case 5:
6469                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6470                                 return true;
6471                         break;
6472                 case 6:
6473                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6474                                 return true;
6475                         break;
6476                 case 7:
6477                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6478                                 return true;
6479                         break;
6480                 }
6481         }
6482         return false;
6483 }
6484
6485 //==================================================================================
6486
6487 // LordHavoc: this stores temporary data used within the same frame
6488
6489 qboolean r_framedata_failed;
6490 static size_t r_framedata_size;
6491 static size_t r_framedata_current;
6492 static void *r_framedata_base;
6493
6494 void R_FrameData_Reset(void)
6495 {
6496         if (r_framedata_base)
6497                 Mem_Free(r_framedata_base);
6498         r_framedata_base = NULL;
6499         r_framedata_size = 0;
6500         r_framedata_current = 0;
6501         r_framedata_failed = false;
6502 }
6503
6504 void R_FrameData_NewFrame(void)
6505 {
6506         size_t wantedsize;
6507         if (r_framedata_failed)
6508                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6509         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6510         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6511         if (r_framedata_size != wantedsize)
6512         {
6513                 r_framedata_size = wantedsize;
6514                 if (r_framedata_base)
6515                         Mem_Free(r_framedata_base);
6516                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6517         }
6518         r_framedata_current = 0;
6519         r_framedata_failed = false;
6520 }
6521
6522 void *R_FrameData_Alloc(size_t size)
6523 {
6524         void *data;
6525
6526         // align to 16 byte boundary
6527         size = (size + 15) & ~15;
6528         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6529         r_framedata_current += size;
6530
6531         // check overflow
6532         if (r_framedata_current > r_framedata_size)
6533                 r_framedata_failed = true;
6534
6535         // return NULL on everything after a failure
6536         if (r_framedata_failed)
6537                 return NULL;
6538
6539         return data;
6540 }
6541
6542 void *R_FrameData_Store(size_t size, void *data)
6543 {
6544         void *d = R_FrameData_Alloc(size);
6545         if (d)
6546                 memcpy(d, data, size);
6547         return d;
6548 }
6549
6550 //==================================================================================
6551
6552 // LordHavoc: animcache originally written by Echon, rewritten since then
6553
6554 /**
6555  * Animation cache prevents re-generating mesh data for an animated model
6556  * multiple times in one frame for lighting, shadowing, reflections, etc.
6557  */
6558
6559 void R_AnimCache_Free(void)
6560 {
6561 }
6562
6563 void R_AnimCache_ClearCache(void)
6564 {
6565         int i;
6566         entity_render_t *ent;
6567
6568         for (i = 0;i < r_refdef.scene.numentities;i++)
6569         {
6570                 ent = r_refdef.scene.entities[i];
6571                 ent->animcache_vertex3f = NULL;
6572                 ent->animcache_normal3f = NULL;
6573                 ent->animcache_svector3f = NULL;
6574                 ent->animcache_tvector3f = NULL;
6575         }
6576 }
6577
6578 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6579 {
6580         dp_model_t *model = ent->model;
6581         int numvertices;
6582         // see if it's already cached this frame
6583         if (ent->animcache_vertex3f)
6584         {
6585                 // add normals/tangents if needed
6586                 if (wantnormals || wanttangents)
6587                 {
6588                         if (ent->animcache_normal3f)
6589                                 wantnormals = false;
6590                         if (ent->animcache_svector3f)
6591                                 wanttangents = false;
6592                         if (wantnormals || wanttangents)
6593                         {
6594                                 numvertices = model->surfmesh.num_vertices;
6595                                 if (wantnormals)
6596                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6597                                 if (wanttangents)
6598                                 {
6599                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6600                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6601                                 }
6602                                 if (!r_framedata_failed)
6603                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6604                         }
6605                 }
6606         }
6607         else
6608         {
6609                 // see if this ent is worth caching
6610                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6611                         return false;
6612                 // get some memory for this entity and generate mesh data
6613                 numvertices = model->surfmesh.num_vertices;
6614                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6615                 if (wantnormals)
6616                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6617                 if (wanttangents)
6618                 {
6619                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6620                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6621                 }
6622                 if (!r_framedata_failed)
6623                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6624         }
6625         return !r_framedata_failed;
6626 }
6627
6628 void R_AnimCache_CacheVisibleEntities(void)
6629 {
6630         int i;
6631         qboolean wantnormals = !r_showsurfaces.integer;
6632         qboolean wanttangents = !r_showsurfaces.integer;
6633
6634         switch(vid.renderpath)
6635         {
6636         case RENDERPATH_GL20:
6637         case RENDERPATH_CGGL:
6638                 break;
6639         case RENDERPATH_GL13:
6640         case RENDERPATH_GL11:
6641                 wanttangents = false;
6642                 break;
6643         }
6644
6645         // TODO: thread this
6646         // NOTE: R_PrepareRTLights() also caches entities
6647
6648         for (i = 0;i < r_refdef.scene.numentities;i++)
6649                 if (r_refdef.viewcache.entityvisible[i])
6650                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6651 }
6652
6653 //==================================================================================
6654
6655 static void R_View_UpdateEntityLighting (void)
6656 {
6657         int i;
6658         entity_render_t *ent;
6659         vec3_t tempdiffusenormal, avg;
6660         vec_t f, fa, fd, fdd;
6661         qboolean skipunseen = r_shadows.integer != 1 || R_Shadow_ShadowMappingEnabled();
6662
6663         for (i = 0;i < r_refdef.scene.numentities;i++)
6664         {
6665                 ent = r_refdef.scene.entities[i];
6666
6667                 // skip unseen models
6668                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6669                         continue;
6670
6671                 // skip bsp models
6672                 if (ent->model && ent->model->brush.num_leafs)
6673                 {
6674                         // TODO: use modellight for r_ambient settings on world?
6675                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6676                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6677                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6678                         continue;
6679                 }
6680
6681                 // fetch the lighting from the worldmodel data
6682                 VectorClear(ent->modellight_ambient);
6683                 VectorClear(ent->modellight_diffuse);
6684                 VectorClear(tempdiffusenormal);
6685                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6686                 {
6687                         vec3_t org;
6688                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6689                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6690                         if(ent->flags & RENDER_EQUALIZE)
6691                         {
6692                                 // first fix up ambient lighting...
6693                                 if(r_equalize_entities_minambient.value > 0)
6694                                 {
6695                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6696                                         if(fd > 0)
6697                                         {
6698                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6699                                                 if(fa < r_equalize_entities_minambient.value * fd)
6700                                                 {
6701                                                         // solve:
6702                                                         //   fa'/fd' = minambient
6703                                                         //   fa'+0.25*fd' = fa+0.25*fd
6704                                                         //   ...
6705                                                         //   fa' = fd' * minambient
6706                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6707                                                         //   ...
6708                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6709                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6710                                                         //   ...
6711                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6712                                                         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
6713                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6714                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6715                                                 }
6716                                         }
6717                                 }
6718
6719                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6720                                 {
6721                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6722                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6723                                         if(f > 0)
6724                                         {
6725                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6726                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6727                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6728                                         }
6729                                 }
6730                         }
6731                 }
6732                 else // highly rare
6733                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6734
6735                 // move the light direction into modelspace coordinates for lighting code
6736                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6737                 if(VectorLength2(ent->modellight_lightdir) == 0)
6738                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6739                 VectorNormalize(ent->modellight_lightdir);
6740         }
6741 }
6742
6743 #define MAX_LINEOFSIGHTTRACES 64
6744
6745 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6746 {
6747         int i;
6748         vec3_t boxmins, boxmaxs;
6749         vec3_t start;
6750         vec3_t end;
6751         dp_model_t *model = r_refdef.scene.worldmodel;
6752
6753         if (!model || !model->brush.TraceLineOfSight)
6754                 return true;
6755
6756         // expand the box a little
6757         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6758         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6759         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6760         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6761         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6762         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6763
6764         // return true if eye is inside enlarged box
6765         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6766                 return true;
6767
6768         // try center
6769         VectorCopy(eye, start);
6770         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6771         if (model->brush.TraceLineOfSight(model, start, end))
6772                 return true;
6773
6774         // try various random positions
6775         for (i = 0;i < numsamples;i++)
6776         {
6777                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6778                 if (model->brush.TraceLineOfSight(model, start, end))
6779                         return true;
6780         }
6781
6782         return false;
6783 }
6784
6785
6786 static void R_View_UpdateEntityVisible (void)
6787 {
6788         int i;
6789         int renderimask;
6790         int samples;
6791         entity_render_t *ent;
6792
6793         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6794         if (!r_drawviewmodel.integer)
6795                 renderimask |= RENDER_VIEWMODEL;
6796         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6797         {
6798                 // worldmodel can check visibility
6799                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6800                 for (i = 0;i < r_refdef.scene.numentities;i++)
6801                 {
6802                         ent = r_refdef.scene.entities[i];
6803                         if (!(ent->flags & renderimask))
6804                         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)))
6805                         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))
6806                                 r_refdef.viewcache.entityvisible[i] = true;
6807                 }
6808                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6809                 {
6810                         for (i = 0;i < r_refdef.scene.numentities;i++)
6811                         {
6812                                 ent = r_refdef.scene.entities[i];
6813                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6814                                 {
6815                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6816                                         if (samples < 0)
6817                                                 continue; // temp entities do pvs only
6818                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6819                                                 ent->last_trace_visibility = realtime;
6820                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6821                                                 r_refdef.viewcache.entityvisible[i] = 0;
6822                                 }
6823                         }
6824                 }
6825         }
6826         else
6827         {
6828                 // no worldmodel or it can't check visibility
6829                 for (i = 0;i < r_refdef.scene.numentities;i++)
6830                 {
6831                         ent = r_refdef.scene.entities[i];
6832                         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));
6833                 }
6834         }
6835 }
6836
6837 /// only used if skyrendermasked, and normally returns false
6838 int R_DrawBrushModelsSky (void)
6839 {
6840         int i, sky;
6841         entity_render_t *ent;
6842
6843         sky = false;
6844         for (i = 0;i < r_refdef.scene.numentities;i++)
6845         {
6846                 if (!r_refdef.viewcache.entityvisible[i])
6847                         continue;
6848                 ent = r_refdef.scene.entities[i];
6849                 if (!ent->model || !ent->model->DrawSky)
6850                         continue;
6851                 ent->model->DrawSky(ent);
6852                 sky = true;
6853         }
6854         return sky;
6855 }
6856
6857 static void R_DrawNoModel(entity_render_t *ent);
6858 static void R_DrawModels(void)
6859 {
6860         int i;
6861         entity_render_t *ent;
6862
6863         for (i = 0;i < r_refdef.scene.numentities;i++)
6864         {
6865                 if (!r_refdef.viewcache.entityvisible[i])
6866                         continue;
6867                 ent = r_refdef.scene.entities[i];
6868                 r_refdef.stats.entities++;
6869                 if (ent->model && ent->model->Draw != NULL)
6870                         ent->model->Draw(ent);
6871                 else
6872                         R_DrawNoModel(ent);
6873         }
6874 }
6875
6876 static void R_DrawModelsDepth(void)
6877 {
6878         int i;
6879         entity_render_t *ent;
6880
6881         for (i = 0;i < r_refdef.scene.numentities;i++)
6882         {
6883                 if (!r_refdef.viewcache.entityvisible[i])
6884                         continue;
6885                 ent = r_refdef.scene.entities[i];
6886                 if (ent->model && ent->model->DrawDepth != NULL)
6887                         ent->model->DrawDepth(ent);
6888         }
6889 }
6890
6891 static void R_DrawModelsDebug(void)
6892 {
6893         int i;
6894         entity_render_t *ent;
6895
6896         for (i = 0;i < r_refdef.scene.numentities;i++)
6897         {
6898                 if (!r_refdef.viewcache.entityvisible[i])
6899                         continue;
6900                 ent = r_refdef.scene.entities[i];
6901                 if (ent->model && ent->model->DrawDebug != NULL)
6902                         ent->model->DrawDebug(ent);
6903         }
6904 }
6905
6906 static void R_DrawModelsAddWaterPlanes(void)
6907 {
6908         int i;
6909         entity_render_t *ent;
6910
6911         for (i = 0;i < r_refdef.scene.numentities;i++)
6912         {
6913                 if (!r_refdef.viewcache.entityvisible[i])
6914                         continue;
6915                 ent = r_refdef.scene.entities[i];
6916                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6917                         ent->model->DrawAddWaterPlanes(ent);
6918         }
6919 }
6920
6921 static void R_View_SetFrustum(void)
6922 {
6923         int i;
6924         double slopex, slopey;
6925         vec3_t forward, left, up, origin;
6926
6927         // we can't trust r_refdef.view.forward and friends in reflected scenes
6928         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6929
6930 #if 0
6931         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6932         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6933         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6934         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6935         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6936         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6937         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6938         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6939         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6940         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6941         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6942         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6943 #endif
6944
6945 #if 0
6946         zNear = r_refdef.nearclip;
6947         nudge = 1.0 - 1.0 / (1<<23);
6948         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6949         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6950         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6951         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6952         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6953         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6954         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6955         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6956 #endif
6957
6958
6959
6960 #if 0
6961         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6962         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6963         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6964         r_refdef.view.frustum[0].dist = m[15] - m[12];
6965
6966         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6967         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6968         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6969         r_refdef.view.frustum[1].dist = m[15] + m[12];
6970
6971         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
6972         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
6973         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
6974         r_refdef.view.frustum[2].dist = m[15] - m[13];
6975
6976         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
6977         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
6978         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
6979         r_refdef.view.frustum[3].dist = m[15] + m[13];
6980
6981         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
6982         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
6983         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
6984         r_refdef.view.frustum[4].dist = m[15] - m[14];
6985
6986         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
6987         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
6988         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
6989         r_refdef.view.frustum[5].dist = m[15] + m[14];
6990 #endif
6991
6992         if (r_refdef.view.useperspective)
6993         {
6994                 slopex = 1.0 / r_refdef.view.frustum_x;
6995                 slopey = 1.0 / r_refdef.view.frustum_y;
6996                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
6997                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
6998                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
6999                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7000                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7001
7002                 // Leaving those out was a mistake, those were in the old code, and they
7003                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7004                 // I couldn't reproduce it after adding those normalizations. --blub
7005                 VectorNormalize(r_refdef.view.frustum[0].normal);
7006                 VectorNormalize(r_refdef.view.frustum[1].normal);
7007                 VectorNormalize(r_refdef.view.frustum[2].normal);
7008                 VectorNormalize(r_refdef.view.frustum[3].normal);
7009
7010                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7011                 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]);
7012                 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]);
7013                 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]);
7014                 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]);
7015
7016                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7017                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7018                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7019                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7020                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7021         }
7022         else
7023         {
7024                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7025                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7026                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7027                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7028                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7029                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7030                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7031                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7032                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7033                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7034         }
7035         r_refdef.view.numfrustumplanes = 5;
7036
7037         if (r_refdef.view.useclipplane)
7038         {
7039                 r_refdef.view.numfrustumplanes = 6;
7040                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7041         }
7042
7043         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7044                 PlaneClassify(r_refdef.view.frustum + i);
7045
7046         // LordHavoc: note to all quake engine coders, Quake had a special case
7047         // for 90 degrees which assumed a square view (wrong), so I removed it,
7048         // Quake2 has it disabled as well.
7049
7050         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7051         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7052         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7053         //PlaneClassify(&frustum[0]);
7054
7055         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7056         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7057         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7058         //PlaneClassify(&frustum[1]);
7059
7060         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7061         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7062         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7063         //PlaneClassify(&frustum[2]);
7064
7065         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7066         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7067         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7068         //PlaneClassify(&frustum[3]);
7069
7070         // nearclip plane
7071         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7072         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7073         //PlaneClassify(&frustum[4]);
7074 }
7075
7076 void R_View_Update(void)
7077 {
7078         R_Main_ResizeViewCache();
7079         R_View_SetFrustum();
7080         R_View_WorldVisibility(r_refdef.view.useclipplane);
7081         R_View_UpdateEntityVisible();
7082         R_View_UpdateEntityLighting();
7083 }
7084
7085 void R_SetupView(qboolean allowwaterclippingplane)
7086 {
7087         const float *customclipplane = NULL;
7088         float plane[4];
7089         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7090         {
7091                 // LordHavoc: couldn't figure out how to make this approach the
7092                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7093                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7094                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7095                         dist = r_refdef.view.clipplane.dist;
7096                 plane[0] = r_refdef.view.clipplane.normal[0];
7097                 plane[1] = r_refdef.view.clipplane.normal[1];
7098                 plane[2] = r_refdef.view.clipplane.normal[2];
7099                 plane[3] = dist;
7100                 customclipplane = plane;
7101         }
7102
7103         if (!r_refdef.view.useperspective)
7104                 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);
7105         else if (vid.stencil && r_useinfinitefarclip.integer)
7106                 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);
7107         else
7108                 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);
7109         R_SetViewport(&r_refdef.view.viewport);
7110 }
7111
7112 void R_EntityMatrix(const matrix4x4_t *matrix)
7113 {
7114         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7115         {
7116                 gl_modelmatrixchanged = false;
7117                 gl_modelmatrix = *matrix;
7118                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7119                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7120                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7121                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7122                 CHECKGLERROR
7123                 switch(vid.renderpath)
7124                 {
7125                 case RENDERPATH_GL20:
7126                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7127                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7128                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7129                         break;
7130                 case RENDERPATH_CGGL:
7131 #ifdef SUPPORTCG
7132                         CHECKCGERROR
7133                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7134                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7135                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7136 #endif
7137                         break;
7138                 case RENDERPATH_GL13:
7139                 case RENDERPATH_GL11:
7140                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7141                         break;
7142                 }
7143         }
7144 }
7145
7146 void R_ResetViewRendering2D(void)
7147 {
7148         r_viewport_t viewport;
7149         DrawQ_Finish();
7150
7151         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7152         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);
7153         R_SetViewport(&viewport);
7154         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7155         GL_Color(1, 1, 1, 1);
7156         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7157         GL_BlendFunc(GL_ONE, GL_ZERO);
7158         GL_AlphaTest(false);
7159         GL_ScissorTest(false);
7160         GL_DepthMask(false);
7161         GL_DepthRange(0, 1);
7162         GL_DepthTest(false);
7163         R_EntityMatrix(&identitymatrix);
7164         R_Mesh_ResetTextureState();
7165         GL_PolygonOffset(0, 0);
7166         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7167         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7168         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7169         qglStencilMask(~0);CHECKGLERROR
7170         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7171         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7172         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7173 }
7174
7175 void R_ResetViewRendering3D(void)
7176 {
7177         DrawQ_Finish();
7178
7179         R_SetupView(true);
7180         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7181         GL_Color(1, 1, 1, 1);
7182         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7183         GL_BlendFunc(GL_ONE, GL_ZERO);
7184         GL_AlphaTest(false);
7185         GL_ScissorTest(true);
7186         GL_DepthMask(true);
7187         GL_DepthRange(0, 1);
7188         GL_DepthTest(true);
7189         R_EntityMatrix(&identitymatrix);
7190         R_Mesh_ResetTextureState();
7191         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7192         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7193         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7194         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7195         qglStencilMask(~0);CHECKGLERROR
7196         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7197         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7198         GL_CullFace(r_refdef.view.cullface_back);
7199 }
7200
7201 void R_RenderScene(void);
7202 void R_RenderWaterPlanes(void);
7203
7204 static void R_Water_StartFrame(void)
7205 {
7206         int i;
7207         int waterwidth, waterheight, texturewidth, textureheight;
7208         r_waterstate_waterplane_t *p;
7209
7210         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7211                 return;
7212
7213         switch(vid.renderpath)
7214         {
7215         case RENDERPATH_GL20:
7216         case RENDERPATH_CGGL:
7217                 break;
7218         case RENDERPATH_GL13:
7219         case RENDERPATH_GL11:
7220                 return;
7221         }
7222
7223         // set waterwidth and waterheight to the water resolution that will be
7224         // used (often less than the screen resolution for faster rendering)
7225         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7226         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7227
7228         // calculate desired texture sizes
7229         // can't use water if the card does not support the texture size
7230         if (!r_water.integer || r_showsurfaces.integer)
7231                 texturewidth = textureheight = waterwidth = waterheight = 0;
7232         else if (vid.support.arb_texture_non_power_of_two)
7233         {
7234                 texturewidth = waterwidth;
7235                 textureheight = waterheight;
7236         }
7237         else
7238         {
7239                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7240                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7241         }
7242
7243         // allocate textures as needed
7244         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7245         {
7246                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7247                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7248                 {
7249                         if (p->texture_refraction)
7250                                 R_FreeTexture(p->texture_refraction);
7251                         p->texture_refraction = NULL;
7252                         if (p->texture_reflection)
7253                                 R_FreeTexture(p->texture_reflection);
7254                         p->texture_reflection = NULL;
7255                 }
7256                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7257                 r_waterstate.texturewidth = texturewidth;
7258                 r_waterstate.textureheight = textureheight;
7259         }
7260
7261         if (r_waterstate.texturewidth)
7262         {
7263                 r_waterstate.enabled = true;
7264
7265                 // when doing a reduced render (HDR) we want to use a smaller area
7266                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7267                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7268
7269                 // set up variables that will be used in shader setup
7270                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7271                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7272                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7273                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7274         }
7275
7276         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7277         r_waterstate.numwaterplanes = 0;
7278 }
7279
7280 void R_Water_AddWaterPlane(msurface_t *surface)
7281 {
7282         int triangleindex, planeindex;
7283         const int *e;
7284         vec3_t vert[3];
7285         vec3_t normal;
7286         vec3_t center;
7287         mplane_t plane;
7288         r_waterstate_waterplane_t *p;
7289         texture_t *t = R_GetCurrentTexture(surface->texture);
7290         // just use the first triangle with a valid normal for any decisions
7291         VectorClear(normal);
7292         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7293         {
7294                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7295                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7296                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7297                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7298                 if (VectorLength2(normal) >= 0.001)
7299                         break;
7300         }
7301
7302         VectorCopy(normal, plane.normal);
7303         VectorNormalize(plane.normal);
7304         plane.dist = DotProduct(vert[0], plane.normal);
7305         PlaneClassify(&plane);
7306         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7307         {
7308                 // skip backfaces (except if nocullface is set)
7309                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7310                         return;
7311                 VectorNegate(plane.normal, plane.normal);
7312                 plane.dist *= -1;
7313                 PlaneClassify(&plane);
7314         }
7315
7316
7317         // find a matching plane if there is one
7318         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7319                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7320                         break;
7321         if (planeindex >= r_waterstate.maxwaterplanes)
7322                 return; // nothing we can do, out of planes
7323
7324         // if this triangle does not fit any known plane rendered this frame, add one
7325         if (planeindex >= r_waterstate.numwaterplanes)
7326         {
7327                 // store the new plane
7328                 r_waterstate.numwaterplanes++;
7329                 p->plane = plane;
7330                 // clear materialflags and pvs
7331                 p->materialflags = 0;
7332                 p->pvsvalid = false;
7333         }
7334         // merge this surface's materialflags into the waterplane
7335         p->materialflags |= t->currentmaterialflags;
7336         // merge this surface's PVS into the waterplane
7337         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7338         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7339          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7340         {
7341                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7342                 p->pvsvalid = true;
7343         }
7344 }
7345
7346 static void R_Water_ProcessPlanes(void)
7347 {
7348         r_refdef_view_t originalview;
7349         r_refdef_view_t myview;
7350         int planeindex;
7351         r_waterstate_waterplane_t *p;
7352
7353         originalview = r_refdef.view;
7354
7355         // make sure enough textures are allocated
7356         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7357         {
7358                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7359                 {
7360                         if (!p->texture_refraction)
7361                                 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);
7362                         if (!p->texture_refraction)
7363                                 goto error;
7364                 }
7365
7366                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7367                 {
7368                         if (!p->texture_reflection)
7369                                 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);
7370                         if (!p->texture_reflection)
7371                                 goto error;
7372                 }
7373         }
7374
7375         // render views
7376         r_refdef.view = originalview;
7377         r_refdef.view.showdebug = false;
7378         r_refdef.view.width = r_waterstate.waterwidth;
7379         r_refdef.view.height = r_waterstate.waterheight;
7380         r_refdef.view.useclipplane = true;
7381         myview = r_refdef.view;
7382         r_waterstate.renderingscene = true;
7383         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7384         {
7385                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7386                 {
7387                         r_refdef.view = myview;
7388                         // render reflected scene and copy into texture
7389                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7390                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7391                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7392                         r_refdef.view.clipplane = p->plane;
7393                         // reverse the cullface settings for this render
7394                         r_refdef.view.cullface_front = GL_FRONT;
7395                         r_refdef.view.cullface_back = GL_BACK;
7396                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7397                         {
7398                                 r_refdef.view.usecustompvs = true;
7399                                 if (p->pvsvalid)
7400                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7401                                 else
7402                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7403                         }
7404
7405                         R_ResetViewRendering3D();
7406                         R_ClearScreen(r_refdef.fogenabled);
7407                         R_View_Update();
7408                         R_RenderScene();
7409
7410                         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);
7411                 }
7412
7413                 // render the normal view scene and copy into texture
7414                 // (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)
7415                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7416                 {
7417                         r_refdef.view = myview;
7418                         r_refdef.view.clipplane = p->plane;
7419                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7420                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7421                         PlaneClassify(&r_refdef.view.clipplane);
7422
7423                         R_ResetViewRendering3D();
7424                         R_ClearScreen(r_refdef.fogenabled);
7425                         R_View_Update();
7426                         R_RenderScene();
7427
7428                         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);
7429                 }
7430
7431         }
7432         r_waterstate.renderingscene = false;
7433         r_refdef.view = originalview;
7434         R_ResetViewRendering3D();
7435         R_ClearScreen(r_refdef.fogenabled);
7436         R_View_Update();
7437         return;
7438 error:
7439         r_refdef.view = originalview;
7440         r_waterstate.renderingscene = false;
7441         Cvar_SetValueQuick(&r_water, 0);
7442         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7443         return;
7444 }
7445
7446 void R_Bloom_StartFrame(void)
7447 {
7448         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7449
7450         switch(vid.renderpath)
7451         {
7452         case RENDERPATH_GL20:
7453         case RENDERPATH_CGGL:
7454                 break;
7455         case RENDERPATH_GL13:
7456         case RENDERPATH_GL11:
7457                 return;
7458         }
7459
7460         // set bloomwidth and bloomheight to the bloom resolution that will be
7461         // used (often less than the screen resolution for faster rendering)
7462         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7463         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7464         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7465         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7466         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7467
7468         // calculate desired texture sizes
7469         if (vid.support.arb_texture_non_power_of_two)
7470         {
7471                 screentexturewidth = r_refdef.view.width;
7472                 screentextureheight = r_refdef.view.height;
7473                 bloomtexturewidth = r_bloomstate.bloomwidth;
7474                 bloomtextureheight = r_bloomstate.bloomheight;
7475         }
7476         else
7477         {
7478                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7479                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7480                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7481                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7482         }
7483
7484         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))
7485         {
7486                 Cvar_SetValueQuick(&r_hdr, 0);
7487                 Cvar_SetValueQuick(&r_bloom, 0);
7488                 Cvar_SetValueQuick(&r_motionblur, 0);
7489                 Cvar_SetValueQuick(&r_damageblur, 0);
7490         }
7491
7492         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)))
7493                 screentexturewidth = screentextureheight = 0;
7494         if (!r_hdr.integer && !r_bloom.integer)
7495                 bloomtexturewidth = bloomtextureheight = 0;
7496
7497         // allocate textures as needed
7498         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7499         {
7500                 if (r_bloomstate.texture_screen)
7501                         R_FreeTexture(r_bloomstate.texture_screen);
7502                 r_bloomstate.texture_screen = NULL;
7503                 r_bloomstate.screentexturewidth = screentexturewidth;
7504                 r_bloomstate.screentextureheight = screentextureheight;
7505                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7506                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7507         }
7508         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7509         {
7510                 if (r_bloomstate.texture_bloom)
7511                         R_FreeTexture(r_bloomstate.texture_bloom);
7512                 r_bloomstate.texture_bloom = NULL;
7513                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7514                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7515                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7516                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7517         }
7518
7519         // when doing a reduced render (HDR) we want to use a smaller area
7520         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7521         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7522         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7523         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7524         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7525
7526         // set up a texcoord array for the full resolution screen image
7527         // (we have to keep this around to copy back during final render)
7528         r_bloomstate.screentexcoord2f[0] = 0;
7529         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7530         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7531         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7532         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7533         r_bloomstate.screentexcoord2f[5] = 0;
7534         r_bloomstate.screentexcoord2f[6] = 0;
7535         r_bloomstate.screentexcoord2f[7] = 0;
7536
7537         // set up a texcoord array for the reduced resolution bloom image
7538         // (which will be additive blended over the screen image)
7539         r_bloomstate.bloomtexcoord2f[0] = 0;
7540         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7541         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7542         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7543         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7544         r_bloomstate.bloomtexcoord2f[5] = 0;
7545         r_bloomstate.bloomtexcoord2f[6] = 0;
7546         r_bloomstate.bloomtexcoord2f[7] = 0;
7547
7548         if (r_hdr.integer || r_bloom.integer)
7549         {
7550                 r_bloomstate.enabled = true;
7551                 r_bloomstate.hdr = r_hdr.integer != 0;
7552         }
7553
7554         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);
7555 }
7556
7557 void R_Bloom_CopyBloomTexture(float colorscale)
7558 {
7559         r_refdef.stats.bloom++;
7560
7561         // scale down screen texture to the bloom texture size
7562         CHECKGLERROR
7563         R_SetViewport(&r_bloomstate.viewport);
7564         GL_BlendFunc(GL_ONE, GL_ZERO);
7565         GL_Color(colorscale, colorscale, colorscale, 1);
7566         // TODO: optimize with multitexture or GLSL
7567         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7568         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7569         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7570         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7571
7572         // we now have a bloom image in the framebuffer
7573         // copy it into the bloom image texture for later processing
7574         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);
7575         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7576 }
7577
7578 void R_Bloom_CopyHDRTexture(void)
7579 {
7580         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);
7581         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7582 }
7583
7584 void R_Bloom_MakeTexture(void)
7585 {
7586         int x, range, dir;
7587         float xoffset, yoffset, r, brighten;
7588
7589         r_refdef.stats.bloom++;
7590
7591         R_ResetViewRendering2D();
7592         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7593         R_Mesh_ColorPointer(NULL, 0, 0);
7594
7595         // we have a bloom image in the framebuffer
7596         CHECKGLERROR
7597         R_SetViewport(&r_bloomstate.viewport);
7598
7599         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7600         {
7601                 x *= 2;
7602                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7603                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7604                 GL_Color(r, r, r, 1);
7605                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7606                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7607                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7608                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7609
7610                 // copy the vertically blurred bloom view to a texture
7611                 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);
7612                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7613         }
7614
7615         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7616         brighten = r_bloom_brighten.value;
7617         if (r_hdr.integer)
7618                 brighten *= r_hdr_range.value;
7619         brighten = sqrt(brighten);
7620         if(range >= 1)
7621                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7622         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7623         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7624
7625         for (dir = 0;dir < 2;dir++)
7626         {
7627                 // blend on at multiple vertical offsets to achieve a vertical blur
7628                 // TODO: do offset blends using GLSL
7629                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7630                 GL_BlendFunc(GL_ONE, GL_ZERO);
7631                 for (x = -range;x <= range;x++)
7632                 {
7633                         if (!dir){xoffset = 0;yoffset = x;}
7634                         else {xoffset = x;yoffset = 0;}
7635                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7636                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7637                         // compute a texcoord array with the specified x and y offset
7638                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7639                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7640                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7641                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7642                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7643                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7644                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7645                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7646                         // this r value looks like a 'dot' particle, fading sharply to
7647                         // black at the edges
7648                         // (probably not realistic but looks good enough)
7649                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7650                         //r = brighten/(range*2+1);
7651                         r = brighten / (range * 2 + 1);
7652                         if(range >= 1)
7653                                 r *= (1 - x*x/(float)(range*range));
7654                         GL_Color(r, r, r, 1);
7655                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7656                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7657                         GL_BlendFunc(GL_ONE, GL_ONE);
7658                 }
7659
7660                 // copy the vertically blurred bloom view to a texture
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         // apply subtract last
7666         // (just like it would be in a GLSL shader)
7667         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7668         {
7669                 GL_BlendFunc(GL_ONE, GL_ZERO);
7670                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7671                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7672                 GL_Color(1, 1, 1, 1);
7673                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7674                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7675
7676                 GL_BlendFunc(GL_ONE, GL_ONE);
7677                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7678                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7679                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7680                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7681                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7682                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7683                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7684
7685                 // copy the darkened bloom view to a texture
7686                 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);
7687                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7688         }
7689 }
7690
7691 void R_HDR_RenderBloomTexture(void)
7692 {
7693         int oldwidth, oldheight;
7694         float oldcolorscale;
7695
7696         oldcolorscale = r_refdef.view.colorscale;
7697         oldwidth = r_refdef.view.width;
7698         oldheight = r_refdef.view.height;
7699         r_refdef.view.width = r_bloomstate.bloomwidth;
7700         r_refdef.view.height = r_bloomstate.bloomheight;
7701
7702         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7703         // TODO: add exposure compensation features
7704         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7705
7706         r_refdef.view.showdebug = false;
7707         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7708
7709         R_ResetViewRendering3D();
7710
7711         R_ClearScreen(r_refdef.fogenabled);
7712         if (r_timereport_active)
7713                 R_TimeReport("HDRclear");
7714
7715         R_View_Update();
7716         if (r_timereport_active)
7717                 R_TimeReport("visibility");
7718
7719         // only do secondary renders with HDR if r_hdr is 2 or higher
7720         r_waterstate.numwaterplanes = 0;
7721         if (r_waterstate.enabled && r_hdr.integer >= 2)
7722                 R_RenderWaterPlanes();
7723
7724         r_refdef.view.showdebug = true;
7725         R_RenderScene();
7726         r_waterstate.numwaterplanes = 0;
7727
7728         R_ResetViewRendering2D();
7729
7730         R_Bloom_CopyHDRTexture();
7731         R_Bloom_MakeTexture();
7732
7733         // restore the view settings
7734         r_refdef.view.width = oldwidth;
7735         r_refdef.view.height = oldheight;
7736         r_refdef.view.colorscale = oldcolorscale;
7737
7738         R_ResetViewRendering3D();
7739
7740         R_ClearScreen(r_refdef.fogenabled);
7741         if (r_timereport_active)
7742                 R_TimeReport("viewclear");
7743 }
7744
7745 static void R_BlendView(void)
7746 {
7747         unsigned int permutation;
7748         float uservecs[4][4];
7749
7750         switch (vid.renderpath)
7751         {
7752         case RENDERPATH_GL20:
7753         case RENDERPATH_CGGL:
7754                 permutation =
7755                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7756                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7757                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7758                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7759                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7760
7761                 if (r_bloomstate.texture_screen)
7762                 {
7763                         // make sure the buffer is available
7764                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7765
7766                         R_ResetViewRendering2D();
7767                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7768                         R_Mesh_ColorPointer(NULL, 0, 0);
7769
7770                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7771                         {
7772                                 // declare variables
7773                                 float speed;
7774                                 static float avgspeed;
7775
7776                                 speed = VectorLength(cl.movement_velocity);
7777
7778                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7779                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7780
7781                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7782                                 speed = bound(0, speed, 1);
7783                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7784
7785                                 // calculate values into a standard alpha
7786                                 cl.motionbluralpha = 1 - exp(-
7787                                                 (
7788                                                  (r_motionblur.value * speed / 80)
7789                                                  +
7790                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7791                                                 )
7792                                                 /
7793                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7794                                            );
7795
7796                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7797                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7798                                 // apply the blur
7799                                 if (cl.motionbluralpha > 0)
7800                                 {
7801                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7802                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7803                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7804                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7805                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7806                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7807                                 }
7808                         }
7809
7810                         // copy view into the screen texture
7811                         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);
7812                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7813                 }
7814                 else if (!r_bloomstate.texture_bloom)
7815                 {
7816                         // we may still have to do view tint...
7817                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7818                         {
7819                                 // apply a color tint to the whole view
7820                                 R_ResetViewRendering2D();
7821                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7822                                 R_Mesh_ColorPointer(NULL, 0, 0);
7823                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7824                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7825                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7826                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7827                         }
7828                         break; // no screen processing, no bloom, skip it
7829                 }
7830
7831                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7832                 {
7833                         // render simple bloom effect
7834                         // copy the screen and shrink it and darken it for the bloom process
7835                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7836                         // make the bloom texture
7837                         R_Bloom_MakeTexture();
7838                 }
7839
7840 #if _MSC_VER >= 1400
7841 #define sscanf sscanf_s
7842 #endif
7843                 memset(uservecs, 0, sizeof(uservecs));
7844                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7845                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7846                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7847                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7848
7849                 R_ResetViewRendering2D();
7850                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7851                 R_Mesh_ColorPointer(NULL, 0, 0);
7852                 GL_Color(1, 1, 1, 1);
7853                 GL_BlendFunc(GL_ONE, GL_ZERO);
7854                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7855                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7856
7857                 switch(vid.renderpath)
7858                 {
7859                 case RENDERPATH_GL20:
7860                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7861                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7862                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7863                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7864                         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]);
7865                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7866                         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]);
7867                         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]);
7868                         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]);
7869                         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]);
7870                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7871                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7872                         break;
7873                 case RENDERPATH_CGGL:
7874 #ifdef SUPPORTCG
7875                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7876                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7877                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7878                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7879                         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
7880                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7881                         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
7882                         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
7883                         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
7884                         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
7885                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7886                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7887 #endif
7888                         break;
7889                 default:
7890                         break;
7891                 }
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                 break;
7895         case RENDERPATH_GL13:
7896         case RENDERPATH_GL11:
7897                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7898                 {
7899                         // apply a color tint to the whole view
7900                         R_ResetViewRendering2D();
7901                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7902                         R_Mesh_ColorPointer(NULL, 0, 0);
7903                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7904                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7905                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7906                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7907                 }
7908                 break;
7909         }
7910 }
7911
7912 matrix4x4_t r_waterscrollmatrix;
7913
7914 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7915 {
7916         if (r_refdef.fog_density)
7917         {
7918                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7919                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7920                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7921
7922                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7923                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7924                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7925                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7926
7927                 {
7928                         vec3_t fogvec;
7929                         VectorCopy(r_refdef.fogcolor, fogvec);
7930                         //   color.rgb *= ContrastBoost * SceneBrightness;
7931                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7932                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7933                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7934                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7935                 }
7936         }
7937 }
7938
7939 void R_UpdateVariables(void)
7940 {
7941         R_Textures_Frame();
7942
7943         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7944
7945         r_refdef.farclip = r_farclip_base.value;
7946         if (r_refdef.scene.worldmodel)
7947                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7948         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7949
7950         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7951                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7952         r_refdef.polygonfactor = 0;
7953         r_refdef.polygonoffset = 0;
7954         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7955         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7956
7957         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7958         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7959         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7960         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7961         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7962         if (r_showsurfaces.integer)
7963         {
7964                 r_refdef.scene.rtworld = false;
7965                 r_refdef.scene.rtworldshadows = false;
7966                 r_refdef.scene.rtdlight = false;
7967                 r_refdef.scene.rtdlightshadows = false;
7968                 r_refdef.lightmapintensity = 0;
7969         }
7970
7971         if (gamemode == GAME_NEHAHRA)
7972         {
7973                 if (gl_fogenable.integer)
7974                 {
7975                         r_refdef.oldgl_fogenable = true;
7976                         r_refdef.fog_density = gl_fogdensity.value;
7977                         r_refdef.fog_red = gl_fogred.value;
7978                         r_refdef.fog_green = gl_foggreen.value;
7979                         r_refdef.fog_blue = gl_fogblue.value;
7980                         r_refdef.fog_alpha = 1;
7981                         r_refdef.fog_start = 0;
7982                         r_refdef.fog_end = gl_skyclip.value;
7983                         r_refdef.fog_height = 1<<30;
7984                         r_refdef.fog_fadedepth = 128;
7985                 }
7986                 else if (r_refdef.oldgl_fogenable)
7987                 {
7988                         r_refdef.oldgl_fogenable = false;
7989                         r_refdef.fog_density = 0;
7990                         r_refdef.fog_red = 0;
7991                         r_refdef.fog_green = 0;
7992                         r_refdef.fog_blue = 0;
7993                         r_refdef.fog_alpha = 0;
7994                         r_refdef.fog_start = 0;
7995                         r_refdef.fog_end = 0;
7996                         r_refdef.fog_height = 1<<30;
7997                         r_refdef.fog_fadedepth = 128;
7998                 }
7999         }
8000
8001         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8002         r_refdef.fog_start = max(0, r_refdef.fog_start);
8003         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8004
8005         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8006
8007         if (r_refdef.fog_density && r_drawfog.integer)
8008         {
8009                 r_refdef.fogenabled = true;
8010                 // this is the point where the fog reaches 0.9986 alpha, which we
8011                 // consider a good enough cutoff point for the texture
8012                 // (0.9986 * 256 == 255.6)
8013                 if (r_fog_exp2.integer)
8014                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8015                 else
8016                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8017                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8018                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8019                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8020                 // fog color was already set
8021                 // update the fog texture
8022                 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)
8023                         R_BuildFogTexture();
8024         }
8025         else
8026                 r_refdef.fogenabled = false;
8027
8028         switch(vid.renderpath)
8029         {
8030         case RENDERPATH_GL20:
8031         case RENDERPATH_CGGL:
8032                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8033                 {
8034                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8035                         {
8036                                 // build GLSL gamma texture
8037 #define RAMPWIDTH 256
8038                                 unsigned short ramp[RAMPWIDTH * 3];
8039                                 unsigned char rampbgr[RAMPWIDTH][4];
8040                                 int i;
8041
8042                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8043
8044                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8045                                 for(i = 0; i < RAMPWIDTH; ++i)
8046                                 {
8047                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8048                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8049                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8050                                         rampbgr[i][3] = 0;
8051                                 }
8052                                 if (r_texture_gammaramps)
8053                                 {
8054                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8055                                 }
8056                                 else
8057                                 {
8058                                         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);
8059                                 }
8060                         }
8061                 }
8062                 else
8063                 {
8064                         // remove GLSL gamma texture
8065                 }
8066                 break;
8067         case RENDERPATH_GL13:
8068         case RENDERPATH_GL11:
8069                 break;
8070         }
8071 }
8072
8073 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8074 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8075 /*
8076 ================
8077 R_SelectScene
8078 ================
8079 */
8080 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8081         if( scenetype != r_currentscenetype ) {
8082                 // store the old scenetype
8083                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8084                 r_currentscenetype = scenetype;
8085                 // move in the new scene
8086                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8087         }
8088 }
8089
8090 /*
8091 ================
8092 R_GetScenePointer
8093 ================
8094 */
8095 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8096 {
8097         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8098         if( scenetype == r_currentscenetype ) {
8099                 return &r_refdef.scene;
8100         } else {
8101                 return &r_scenes_store[ scenetype ];
8102         }
8103 }
8104
8105 /*
8106 ================
8107 R_RenderView
8108 ================
8109 */
8110 void R_RenderView(void)
8111 {
8112         if (r_timereport_active)
8113                 R_TimeReport("start");
8114         r_textureframe++; // used only by R_GetCurrentTexture
8115         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8116
8117         if (!r_drawentities.integer)
8118                 r_refdef.scene.numentities = 0;
8119
8120         R_AnimCache_ClearCache();
8121         R_FrameData_NewFrame();
8122
8123         if (r_refdef.view.isoverlay)
8124         {
8125                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8126                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8127                 R_TimeReport("depthclear");
8128
8129                 r_refdef.view.showdebug = false;
8130
8131                 r_waterstate.enabled = false;
8132                 r_waterstate.numwaterplanes = 0;
8133
8134                 R_RenderScene();
8135
8136                 CHECKGLERROR
8137                 return;
8138         }
8139
8140         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8141                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8142
8143         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8144
8145         // break apart the view matrix into vectors for various purposes
8146         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8147         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8148         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8149         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8150         // make an inverted copy of the view matrix for tracking sprites
8151         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8152
8153         R_Shadow_UpdateWorldLightSelection();
8154
8155         R_Bloom_StartFrame();
8156         R_Water_StartFrame();
8157
8158         CHECKGLERROR
8159         if (r_timereport_active)
8160                 R_TimeReport("viewsetup");
8161
8162         R_ResetViewRendering3D();
8163
8164         if (r_refdef.view.clear || r_refdef.fogenabled)
8165         {
8166                 R_ClearScreen(r_refdef.fogenabled);
8167                 if (r_timereport_active)
8168                         R_TimeReport("viewclear");
8169         }
8170         r_refdef.view.clear = true;
8171
8172         // this produces a bloom texture to be used in R_BlendView() later
8173         if (r_hdr.integer && r_bloomstate.bloomwidth)
8174         {
8175                 R_HDR_RenderBloomTexture();
8176                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8177                 r_textureframe++; // used only by R_GetCurrentTexture
8178         }
8179
8180         r_refdef.view.showdebug = true;
8181
8182         R_View_Update();
8183         if (r_timereport_active)
8184                 R_TimeReport("visibility");
8185
8186         r_waterstate.numwaterplanes = 0;
8187         if (r_waterstate.enabled)
8188                 R_RenderWaterPlanes();
8189
8190         R_RenderScene();
8191         r_waterstate.numwaterplanes = 0;
8192
8193         R_BlendView();
8194         if (r_timereport_active)
8195                 R_TimeReport("blendview");
8196
8197         GL_Scissor(0, 0, vid.width, vid.height);
8198         GL_ScissorTest(false);
8199         CHECKGLERROR
8200 }
8201
8202 void R_RenderWaterPlanes(void)
8203 {
8204         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8205         {
8206                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8207                 if (r_timereport_active)
8208                         R_TimeReport("waterworld");
8209         }
8210
8211         // don't let sound skip if going slow
8212         if (r_refdef.scene.extraupdate)
8213                 S_ExtraUpdate ();
8214
8215         R_DrawModelsAddWaterPlanes();
8216         if (r_timereport_active)
8217                 R_TimeReport("watermodels");
8218
8219         if (r_waterstate.numwaterplanes)
8220         {
8221                 R_Water_ProcessPlanes();
8222                 if (r_timereport_active)
8223                         R_TimeReport("waterscenes");
8224         }
8225 }
8226
8227 extern void R_DrawLightningBeams (void);
8228 extern void VM_CL_AddPolygonsToMeshQueue (void);
8229 extern void R_DrawPortals (void);
8230 extern cvar_t cl_locs_show;
8231 static void R_DrawLocs(void);
8232 static void R_DrawEntityBBoxes(void);
8233 static void R_DrawModelDecals(void);
8234 extern void R_DrawModelShadows(void);
8235 extern void R_DrawModelShadowMaps(void);
8236 extern cvar_t cl_decals_newsystem;
8237 extern qboolean r_shadow_usingdeferredprepass;
8238 void R_RenderScene(void)
8239 {
8240         qboolean shadowmapping = false;
8241
8242         r_refdef.stats.renders++;
8243
8244         R_UpdateFogColor();
8245
8246         // don't let sound skip if going slow
8247         if (r_refdef.scene.extraupdate)
8248                 S_ExtraUpdate ();
8249
8250         R_MeshQueue_BeginScene();
8251
8252         R_SkyStartFrame();
8253
8254         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);
8255
8256         if (cl.csqc_vidvars.drawworld)
8257         {
8258                 // don't let sound skip if going slow
8259                 if (r_refdef.scene.extraupdate)
8260                         S_ExtraUpdate ();
8261
8262                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8263                 {
8264                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8265                         if (r_timereport_active)
8266                                 R_TimeReport("worldsky");
8267                 }
8268
8269                 if (R_DrawBrushModelsSky() && r_timereport_active)
8270                         R_TimeReport("bmodelsky");
8271
8272                 if (skyrendermasked && skyrenderlater)
8273                 {
8274                         // we have to force off the water clipping plane while rendering sky
8275                         R_SetupView(false);
8276                         R_Sky();
8277                         R_SetupView(true);
8278                         if (r_timereport_active)
8279                                 R_TimeReport("sky");
8280                 }
8281         }
8282
8283         R_AnimCache_CacheVisibleEntities();
8284         if (r_timereport_active)
8285                 R_TimeReport("animation");
8286
8287         R_Shadow_PrepareLights();
8288         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8289                 R_Shadow_PrepareModelShadows();
8290         if (r_timereport_active)
8291                 R_TimeReport("preparelights");
8292
8293         if (R_Shadow_ShadowMappingEnabled())
8294                 shadowmapping = true;
8295
8296         if (r_shadow_usingdeferredprepass)
8297                 R_Shadow_DrawPrepass();
8298
8299         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8300         {
8301                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8302                 if (r_timereport_active)
8303                         R_TimeReport("worlddepth");
8304         }
8305         if (r_depthfirst.integer >= 2)
8306         {
8307                 R_DrawModelsDepth();
8308                 if (r_timereport_active)
8309                         R_TimeReport("modeldepth");
8310         }
8311
8312         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8313         {
8314                 R_DrawModelShadowMaps();
8315                 R_ResetViewRendering3D();
8316                 // don't let sound skip if going slow
8317                 if (r_refdef.scene.extraupdate)
8318                         S_ExtraUpdate ();
8319         }
8320
8321         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8322         {
8323                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8324                 if (r_timereport_active)
8325                         R_TimeReport("world");
8326         }
8327
8328         // don't let sound skip if going slow
8329         if (r_refdef.scene.extraupdate)
8330                 S_ExtraUpdate ();
8331
8332         R_DrawModels();
8333         if (r_timereport_active)
8334                 R_TimeReport("models");
8335
8336         // don't let sound skip if going slow
8337         if (r_refdef.scene.extraupdate)
8338                 S_ExtraUpdate ();
8339
8340         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8341         {
8342                 R_DrawModelShadows();
8343                 R_ResetViewRendering3D();
8344                 // don't let sound skip if going slow
8345                 if (r_refdef.scene.extraupdate)
8346                         S_ExtraUpdate ();
8347         }
8348
8349         if (!r_shadow_usingdeferredprepass)
8350         {
8351                 R_Shadow_DrawLights();
8352                 if (r_timereport_active)
8353                         R_TimeReport("rtlights");
8354         }
8355
8356         // don't let sound skip if going slow
8357         if (r_refdef.scene.extraupdate)
8358                 S_ExtraUpdate ();
8359
8360         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8361         {
8362                 R_DrawModelShadows();
8363                 R_ResetViewRendering3D();
8364                 // don't let sound skip if going slow
8365                 if (r_refdef.scene.extraupdate)
8366                         S_ExtraUpdate ();
8367         }
8368
8369         if (cl.csqc_vidvars.drawworld)
8370         {
8371                 if (cl_decals_newsystem.integer)
8372                 {
8373                         R_DrawModelDecals();
8374                         if (r_timereport_active)
8375                                 R_TimeReport("modeldecals");
8376                 }
8377                 else
8378                 {
8379                         R_DrawDecals();
8380                         if (r_timereport_active)
8381                                 R_TimeReport("decals");
8382                 }
8383
8384                 R_DrawParticles();
8385                 if (r_timereport_active)
8386                         R_TimeReport("particles");
8387
8388                 R_DrawExplosions();
8389                 if (r_timereport_active)
8390                         R_TimeReport("explosions");
8391
8392                 R_DrawLightningBeams();
8393                 if (r_timereport_active)
8394                         R_TimeReport("lightning");
8395         }
8396
8397         VM_CL_AddPolygonsToMeshQueue();
8398
8399         if (r_refdef.view.showdebug)
8400         {
8401                 if (cl_locs_show.integer)
8402                 {
8403                         R_DrawLocs();
8404                         if (r_timereport_active)
8405                                 R_TimeReport("showlocs");
8406                 }
8407
8408                 if (r_drawportals.integer)
8409                 {
8410                         R_DrawPortals();
8411                         if (r_timereport_active)
8412                                 R_TimeReport("portals");
8413                 }
8414
8415                 if (r_showbboxes.value > 0)
8416                 {
8417                         R_DrawEntityBBoxes();
8418                         if (r_timereport_active)
8419                                 R_TimeReport("bboxes");
8420                 }
8421         }
8422
8423         R_MeshQueue_RenderTransparent();
8424         if (r_timereport_active)
8425                 R_TimeReport("drawtrans");
8426
8427         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))
8428         {
8429                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8430                 if (r_timereport_active)
8431                         R_TimeReport("worlddebug");
8432                 R_DrawModelsDebug();
8433                 if (r_timereport_active)
8434                         R_TimeReport("modeldebug");
8435         }
8436
8437         if (cl.csqc_vidvars.drawworld)
8438         {
8439                 R_Shadow_DrawCoronas();
8440                 if (r_timereport_active)
8441                         R_TimeReport("coronas");
8442         }
8443
8444         // don't let sound skip if going slow
8445         if (r_refdef.scene.extraupdate)
8446                 S_ExtraUpdate ();
8447
8448         R_ResetViewRendering2D();
8449 }
8450
8451 static const unsigned short bboxelements[36] =
8452 {
8453         5, 1, 3, 5, 3, 7,
8454         6, 2, 0, 6, 0, 4,
8455         7, 3, 2, 7, 2, 6,
8456         4, 0, 1, 4, 1, 5,
8457         4, 5, 7, 4, 7, 6,
8458         1, 0, 2, 1, 2, 3,
8459 };
8460
8461 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8462 {
8463         int i;
8464         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8465
8466         RSurf_ActiveWorldEntity();
8467
8468         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8469         GL_DepthMask(false);
8470         GL_DepthRange(0, 1);
8471         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8472         R_Mesh_ResetTextureState();
8473
8474         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8475         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8476         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8477         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8478         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8479         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8480         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8481         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8482         R_FillColors(color4f, 8, cr, cg, cb, ca);
8483         if (r_refdef.fogenabled)
8484         {
8485                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8486                 {
8487                         f1 = RSurf_FogVertex(v);
8488                         f2 = 1 - f1;
8489                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8490                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8491                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8492                 }
8493         }
8494         R_Mesh_VertexPointer(vertex3f, 0, 0);
8495         R_Mesh_ColorPointer(color4f, 0, 0);
8496         R_Mesh_ResetTextureState();
8497         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8498         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8499 }
8500
8501 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8502 {
8503         int i;
8504         float color[4];
8505         prvm_edict_t *edict;
8506         prvm_prog_t *prog_save = prog;
8507
8508         // this function draws bounding boxes of server entities
8509         if (!sv.active)
8510                 return;
8511
8512         GL_CullFace(GL_NONE);
8513         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8514
8515         prog = 0;
8516         SV_VM_Begin();
8517         for (i = 0;i < numsurfaces;i++)
8518         {
8519                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8520                 switch ((int)edict->fields.server->solid)
8521                 {
8522                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8523                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8524                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8525                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8526                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8527                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8528                 }
8529                 color[3] *= r_showbboxes.value;
8530                 color[3] = bound(0, color[3], 1);
8531                 GL_DepthTest(!r_showdisabledepthtest.integer);
8532                 GL_CullFace(r_refdef.view.cullface_front);
8533                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8534         }
8535         SV_VM_End();
8536         prog = prog_save;
8537 }
8538
8539 static void R_DrawEntityBBoxes(void)
8540 {
8541         int i;
8542         prvm_edict_t *edict;
8543         vec3_t center;
8544         prvm_prog_t *prog_save = prog;
8545
8546         // this function draws bounding boxes of server entities
8547         if (!sv.active)
8548                 return;
8549
8550         prog = 0;
8551         SV_VM_Begin();
8552         for (i = 0;i < prog->num_edicts;i++)
8553         {
8554                 edict = PRVM_EDICT_NUM(i);
8555                 if (edict->priv.server->free)
8556                         continue;
8557                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8558                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8559                         continue;
8560                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8561                         continue;
8562                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8563                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8564         }
8565         SV_VM_End();
8566         prog = prog_save;
8567 }
8568
8569 static const int nomodelelement3i[24] =
8570 {
8571         5, 2, 0,
8572         5, 1, 2,
8573         5, 0, 3,
8574         5, 3, 1,
8575         0, 2, 4,
8576         2, 1, 4,
8577         3, 0, 4,
8578         1, 3, 4
8579 };
8580
8581 static const unsigned short nomodelelement3s[24] =
8582 {
8583         5, 2, 0,
8584         5, 1, 2,
8585         5, 0, 3,
8586         5, 3, 1,
8587         0, 2, 4,
8588         2, 1, 4,
8589         3, 0, 4,
8590         1, 3, 4
8591 };
8592
8593 static const float nomodelvertex3f[6*3] =
8594 {
8595         -16,   0,   0,
8596          16,   0,   0,
8597           0, -16,   0,
8598           0,  16,   0,
8599           0,   0, -16,
8600           0,   0,  16
8601 };
8602
8603 static const float nomodelcolor4f[6*4] =
8604 {
8605         0.0f, 0.0f, 0.5f, 1.0f,
8606         0.0f, 0.0f, 0.5f, 1.0f,
8607         0.0f, 0.5f, 0.0f, 1.0f,
8608         0.0f, 0.5f, 0.0f, 1.0f,
8609         0.5f, 0.0f, 0.0f, 1.0f,
8610         0.5f, 0.0f, 0.0f, 1.0f
8611 };
8612
8613 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8614 {
8615         int i;
8616         float f1, f2, *c;
8617         float color4f[6*4];
8618
8619         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);
8620
8621         // this is only called once per entity so numsurfaces is always 1, and
8622         // surfacelist is always {0}, so this code does not handle batches
8623
8624         if (rsurface.ent_flags & RENDER_ADDITIVE)
8625         {
8626                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8627                 GL_DepthMask(false);
8628         }
8629         else if (rsurface.colormod[3] < 1)
8630         {
8631                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8632                 GL_DepthMask(false);
8633         }
8634         else
8635         {
8636                 GL_BlendFunc(GL_ONE, GL_ZERO);
8637                 GL_DepthMask(true);
8638         }
8639         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8640         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8641         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8642         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8643         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8644         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8645         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8646         R_Mesh_ColorPointer(color4f, 0, 0);
8647         for (i = 0, c = color4f;i < 6;i++, c += 4)
8648         {
8649                 c[0] *= rsurface.colormod[0];
8650                 c[1] *= rsurface.colormod[1];
8651                 c[2] *= rsurface.colormod[2];
8652                 c[3] *= rsurface.colormod[3];
8653         }
8654         if (r_refdef.fogenabled)
8655         {
8656                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8657                 {
8658                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8659                         f2 = 1 - f1;
8660                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8661                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8662                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8663                 }
8664         }
8665         R_Mesh_ResetTextureState();
8666         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8667 }
8668
8669 void R_DrawNoModel(entity_render_t *ent)
8670 {
8671         vec3_t org;
8672         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8673         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8674                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8675         else
8676                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8677 }
8678
8679 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8680 {
8681         vec3_t right1, right2, diff, normal;
8682
8683         VectorSubtract (org2, org1, normal);
8684
8685         // calculate 'right' vector for start
8686         VectorSubtract (r_refdef.view.origin, org1, diff);
8687         CrossProduct (normal, diff, right1);
8688         VectorNormalize (right1);
8689
8690         // calculate 'right' vector for end
8691         VectorSubtract (r_refdef.view.origin, org2, diff);
8692         CrossProduct (normal, diff, right2);
8693         VectorNormalize (right2);
8694
8695         vert[ 0] = org1[0] + width * right1[0];
8696         vert[ 1] = org1[1] + width * right1[1];
8697         vert[ 2] = org1[2] + width * right1[2];
8698         vert[ 3] = org1[0] - width * right1[0];
8699         vert[ 4] = org1[1] - width * right1[1];
8700         vert[ 5] = org1[2] - width * right1[2];
8701         vert[ 6] = org2[0] - width * right2[0];
8702         vert[ 7] = org2[1] - width * right2[1];
8703         vert[ 8] = org2[2] - width * right2[2];
8704         vert[ 9] = org2[0] + width * right2[0];
8705         vert[10] = org2[1] + width * right2[1];
8706         vert[11] = org2[2] + width * right2[2];
8707 }
8708
8709 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)
8710 {
8711         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8712         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8713         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8714         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8715         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8716         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8717         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8718         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8719         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8720         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8721         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8722         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8723 }
8724
8725 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8726 {
8727         int i;
8728         float *vertex3f;
8729         float v[3];
8730         VectorSet(v, x, y, z);
8731         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8732                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8733                         break;
8734         if (i == mesh->numvertices)
8735         {
8736                 if (mesh->numvertices < mesh->maxvertices)
8737                 {
8738                         VectorCopy(v, vertex3f);
8739                         mesh->numvertices++;
8740                 }
8741                 return mesh->numvertices;
8742         }
8743         else
8744                 return i;
8745 }
8746
8747 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8748 {
8749         int i;
8750         int *e, element[3];
8751         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8752         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8753         e = mesh->element3i + mesh->numtriangles * 3;
8754         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8755         {
8756                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8757                 if (mesh->numtriangles < mesh->maxtriangles)
8758                 {
8759                         *e++ = element[0];
8760                         *e++ = element[1];
8761                         *e++ = element[2];
8762                         mesh->numtriangles++;
8763                 }
8764                 element[1] = element[2];
8765         }
8766 }
8767
8768 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8769 {
8770         int i;
8771         int *e, element[3];
8772         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8773         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8774         e = mesh->element3i + mesh->numtriangles * 3;
8775         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8776         {
8777                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8778                 if (mesh->numtriangles < mesh->maxtriangles)
8779                 {
8780                         *e++ = element[0];
8781                         *e++ = element[1];
8782                         *e++ = element[2];
8783                         mesh->numtriangles++;
8784                 }
8785                 element[1] = element[2];
8786         }
8787 }
8788
8789 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8790 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8791 {
8792         int planenum, planenum2;
8793         int w;
8794         int tempnumpoints;
8795         mplane_t *plane, *plane2;
8796         double maxdist;
8797         double temppoints[2][256*3];
8798         // figure out how large a bounding box we need to properly compute this brush
8799         maxdist = 0;
8800         for (w = 0;w < numplanes;w++)
8801                 maxdist = max(maxdist, fabs(planes[w].dist));
8802         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8803         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8804         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8805         {
8806                 w = 0;
8807                 tempnumpoints = 4;
8808                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8809                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8810                 {
8811                         if (planenum2 == planenum)
8812                                 continue;
8813                         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);
8814                         w = !w;
8815                 }
8816                 if (tempnumpoints < 3)
8817                         continue;
8818                 // generate elements forming a triangle fan for this polygon
8819                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8820         }
8821 }
8822
8823 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)
8824 {
8825         texturelayer_t *layer;
8826         layer = t->currentlayers + t->currentnumlayers++;
8827         layer->type = type;
8828         layer->depthmask = depthmask;
8829         layer->blendfunc1 = blendfunc1;
8830         layer->blendfunc2 = blendfunc2;
8831         layer->texture = texture;
8832         layer->texmatrix = *matrix;
8833         layer->color[0] = r;
8834         layer->color[1] = g;
8835         layer->color[2] = b;
8836         layer->color[3] = a;
8837 }
8838
8839 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8840 {
8841         double index, f;
8842         index = parms[2] + r_refdef.scene.time * parms[3];
8843         index -= floor(index);
8844         switch (func)
8845         {
8846         default:
8847         case Q3WAVEFUNC_NONE:
8848         case Q3WAVEFUNC_NOISE:
8849         case Q3WAVEFUNC_COUNT:
8850                 f = 0;
8851                 break;
8852         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8853         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8854         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8855         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8856         case Q3WAVEFUNC_TRIANGLE:
8857                 index *= 4;
8858                 f = index - floor(index);
8859                 if (index < 1)
8860                         f = f;
8861                 else if (index < 2)
8862                         f = 1 - f;
8863                 else if (index < 3)
8864                         f = -f;
8865                 else
8866                         f = -(1 - f);
8867                 break;
8868         }
8869         return (float)(parms[0] + parms[1] * f);
8870 }
8871
8872 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8873 {
8874         int w, h, idx;
8875         float f;
8876         float tcmat[12];
8877         matrix4x4_t matrix, temp;
8878         switch(tcmod->tcmod)
8879         {
8880                 case Q3TCMOD_COUNT:
8881                 case Q3TCMOD_NONE:
8882                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8883                                 matrix = r_waterscrollmatrix;
8884                         else
8885                                 matrix = identitymatrix;
8886                         break;
8887                 case Q3TCMOD_ENTITYTRANSLATE:
8888                         // this is used in Q3 to allow the gamecode to control texcoord
8889                         // scrolling on the entity, which is not supported in darkplaces yet.
8890                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8891                         break;
8892                 case Q3TCMOD_ROTATE:
8893                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8894                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8895                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8896                         break;
8897                 case Q3TCMOD_SCALE:
8898                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8899                         break;
8900                 case Q3TCMOD_SCROLL:
8901                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8902                         break;
8903                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8904                         w = (int) tcmod->parms[0];
8905                         h = (int) tcmod->parms[1];
8906                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8907                         f = f - floor(f);
8908                         idx = (int) floor(f * w * h);
8909                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8910                         break;
8911                 case Q3TCMOD_STRETCH:
8912                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8913                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8914                         break;
8915                 case Q3TCMOD_TRANSFORM:
8916                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8917                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8918                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8919                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8920                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8921                         break;
8922                 case Q3TCMOD_TURBULENT:
8923                         // this is handled in the RSurf_PrepareVertices function
8924                         matrix = identitymatrix;
8925                         break;
8926         }
8927         temp = *texmatrix;
8928         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8929 }
8930
8931 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8932 {
8933         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8934         char name[MAX_QPATH];
8935         skinframe_t *skinframe;
8936         unsigned char pixels[296*194];
8937         strlcpy(cache->name, skinname, sizeof(cache->name));
8938         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8939         if (developer_loading.integer)
8940                 Con_Printf("loading %s\n", name);
8941         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8942         if (!skinframe || !skinframe->base)
8943         {
8944                 unsigned char *f;
8945                 fs_offset_t filesize;
8946                 skinframe = NULL;
8947                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8948                 if (f)
8949                 {
8950                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8951                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8952                         Mem_Free(f);
8953                 }
8954         }
8955         cache->skinframe = skinframe;
8956 }
8957
8958 texture_t *R_GetCurrentTexture(texture_t *t)
8959 {
8960         int i;
8961         const entity_render_t *ent = rsurface.entity;
8962         dp_model_t *model = ent->model;
8963         q3shaderinfo_layer_tcmod_t *tcmod;
8964
8965         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8966                 return t->currentframe;
8967         t->update_lastrenderframe = r_textureframe;
8968         t->update_lastrenderentity = (void *)ent;
8969
8970         // switch to an alternate material if this is a q1bsp animated material
8971         {
8972                 texture_t *texture = t;
8973                 int s = rsurface.ent_skinnum;
8974                 if ((unsigned int)s >= (unsigned int)model->numskins)
8975                         s = 0;
8976                 if (model->skinscenes)
8977                 {
8978                         if (model->skinscenes[s].framecount > 1)
8979                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8980                         else
8981                                 s = model->skinscenes[s].firstframe;
8982                 }
8983                 if (s > 0)
8984                         t = t + s * model->num_surfaces;
8985                 if (t->animated)
8986                 {
8987                         // use an alternate animation if the entity's frame is not 0,
8988                         // and only if the texture has an alternate animation
8989                         if (rsurface.ent_alttextures && t->anim_total[1])
8990                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
8991                         else
8992                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
8993                 }
8994                 texture->currentframe = t;
8995         }
8996
8997         // update currentskinframe to be a qw skin or animation frame
8998         if (rsurface.ent_qwskin >= 0)
8999         {
9000                 i = rsurface.ent_qwskin;
9001                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9002                 {
9003                         r_qwskincache_size = cl.maxclients;
9004                         if (r_qwskincache)
9005                                 Mem_Free(r_qwskincache);
9006                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9007                 }
9008                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9009                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9010                 t->currentskinframe = r_qwskincache[i].skinframe;
9011                 if (t->currentskinframe == NULL)
9012                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9013         }
9014         else if (t->numskinframes >= 2)
9015                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9016         if (t->backgroundnumskinframes >= 2)
9017                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9018
9019         t->currentmaterialflags = t->basematerialflags;
9020         t->currentalpha = rsurface.colormod[3];
9021         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9022                 t->currentalpha *= r_wateralpha.value;
9023         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9024                 t->currentalpha *= t->r_water_wateralpha;
9025         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9026                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9027         if (!(rsurface.ent_flags & RENDER_LIGHT))
9028                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9029         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9030         {
9031                 // pick a model lighting mode
9032                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9033                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9034                 else
9035                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9036         }
9037         if (rsurface.ent_flags & RENDER_ADDITIVE)
9038                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9039         else if (t->currentalpha < 1)
9040                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9041         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9042                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9043         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9044                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9045         if (t->backgroundnumskinframes)
9046                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9047         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9048         {
9049                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9050                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9051         }
9052         else
9053                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9054         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9055                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9056
9057         // there is no tcmod
9058         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9059         {
9060                 t->currenttexmatrix = r_waterscrollmatrix;
9061                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9062         }
9063         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9064         {
9065                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9066                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9067         }
9068
9069         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9070                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9071         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9072                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9073
9074         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9075         if (t->currentskinframe->qpixels)
9076                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9077         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9078         if (!t->basetexture)
9079                 t->basetexture = r_texture_notexture;
9080         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9081         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9082         t->nmaptexture = t->currentskinframe->nmap;
9083         if (!t->nmaptexture)
9084                 t->nmaptexture = r_texture_blanknormalmap;
9085         t->glosstexture = r_texture_black;
9086         t->glowtexture = t->currentskinframe->glow;
9087         t->fogtexture = t->currentskinframe->fog;
9088         t->reflectmasktexture = t->currentskinframe->reflect;
9089         if (t->backgroundnumskinframes)
9090         {
9091                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9092                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9093                 t->backgroundglosstexture = r_texture_black;
9094                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9095                 if (!t->backgroundnmaptexture)
9096                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9097         }
9098         else
9099         {
9100                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9101                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9102                 t->backgroundglosstexture = r_texture_black;
9103                 t->backgroundglowtexture = NULL;
9104         }
9105         t->specularpower = r_shadow_glossexponent.value;
9106         // TODO: store reference values for these in the texture?
9107         t->specularscale = 0;
9108         if (r_shadow_gloss.integer > 0)
9109         {
9110                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9111                 {
9112                         if (r_shadow_glossintensity.value > 0)
9113                         {
9114                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9115                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9116                                 t->specularscale = r_shadow_glossintensity.value;
9117                         }
9118                 }
9119                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9120                 {
9121                         t->glosstexture = r_texture_white;
9122                         t->backgroundglosstexture = r_texture_white;
9123                         t->specularscale = r_shadow_gloss2intensity.value;
9124                         t->specularpower = r_shadow_gloss2exponent.value;
9125                 }
9126         }
9127         t->specularscale *= t->specularscalemod;
9128         t->specularpower *= t->specularpowermod;
9129
9130         // lightmaps mode looks bad with dlights using actual texturing, so turn
9131         // off the colormap and glossmap, but leave the normalmap on as it still
9132         // accurately represents the shading involved
9133         if (gl_lightmaps.integer)
9134         {
9135                 t->basetexture = r_texture_grey128;
9136                 t->pantstexture = r_texture_black;
9137                 t->shirttexture = r_texture_black;
9138                 t->nmaptexture = r_texture_blanknormalmap;
9139                 t->glosstexture = r_texture_black;
9140                 t->glowtexture = NULL;
9141                 t->fogtexture = NULL;
9142                 t->reflectmasktexture = NULL;
9143                 t->backgroundbasetexture = NULL;
9144                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9145                 t->backgroundglosstexture = r_texture_black;
9146                 t->backgroundglowtexture = NULL;
9147                 t->specularscale = 0;
9148                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9149         }
9150
9151         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9152         VectorClear(t->dlightcolor);
9153         t->currentnumlayers = 0;
9154         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9155         {
9156                 int blendfunc1, blendfunc2;
9157                 qboolean depthmask;
9158                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9159                 {
9160                         blendfunc1 = GL_SRC_ALPHA;
9161                         blendfunc2 = GL_ONE;
9162                 }
9163                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9164                 {
9165                         blendfunc1 = GL_SRC_ALPHA;
9166                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9167                 }
9168                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9169                 {
9170                         blendfunc1 = t->customblendfunc[0];
9171                         blendfunc2 = t->customblendfunc[1];
9172                 }
9173                 else
9174                 {
9175                         blendfunc1 = GL_ONE;
9176                         blendfunc2 = GL_ZERO;
9177                 }
9178                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9179                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9180                 {
9181                         // fullbright is not affected by r_refdef.lightmapintensity
9182                         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]);
9183                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9184                                 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]);
9185                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9186                                 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]);
9187                 }
9188                 else
9189                 {
9190                         vec3_t ambientcolor;
9191                         float colorscale;
9192                         // set the color tint used for lights affecting this surface
9193                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9194                         colorscale = 2;
9195                         // q3bsp has no lightmap updates, so the lightstylevalue that
9196                         // would normally be baked into the lightmap must be
9197                         // applied to the color
9198                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9199                         if (model->type == mod_brushq3)
9200                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9201                         colorscale *= r_refdef.lightmapintensity;
9202                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9203                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9204                         // basic lit geometry
9205                         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]);
9206                         // add pants/shirt if needed
9207                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9208                                 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]);
9209                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9210                                 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]);
9211                         // now add ambient passes if needed
9212                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9213                         {
9214                                 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]);
9215                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9216                                         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]);
9217                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9218                                         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]);
9219                         }
9220                 }
9221                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9222                         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]);
9223                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9224                 {
9225                         // if this is opaque use alpha blend which will darken the earlier
9226                         // passes cheaply.
9227                         //
9228                         // if this is an alpha blended material, all the earlier passes
9229                         // were darkened by fog already, so we only need to add the fog
9230                         // color ontop through the fog mask texture
9231                         //
9232                         // if this is an additive blended material, all the earlier passes
9233                         // were darkened by fog already, and we should not add fog color
9234                         // (because the background was not darkened, there is no fog color
9235                         // that was lost behind it).
9236                         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]);
9237                 }
9238         }
9239
9240         return t->currentframe;
9241 }
9242
9243 rsurfacestate_t rsurface;
9244
9245 void R_Mesh_ResizeArrays(int newvertices)
9246 {
9247         float *base;
9248         if (rsurface.array_size >= newvertices)
9249                 return;
9250         if (rsurface.array_modelvertex3f)
9251                 Mem_Free(rsurface.array_modelvertex3f);
9252         rsurface.array_size = (newvertices + 1023) & ~1023;
9253         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9254         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9255         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9256         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9257         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9258         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9259         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9260         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9261         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9262         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9263         rsurface.array_color4f           = base + rsurface.array_size * 27;
9264         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9265 }
9266
9267 void RSurf_ActiveWorldEntity(void)
9268 {
9269         dp_model_t *model = r_refdef.scene.worldmodel;
9270         //if (rsurface.entity == r_refdef.scene.worldentity)
9271         //      return;
9272         rsurface.entity = r_refdef.scene.worldentity;
9273         rsurface.skeleton = NULL;
9274         rsurface.ent_skinnum = 0;
9275         rsurface.ent_qwskin = -1;
9276         rsurface.ent_shadertime = 0;
9277         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9278         if (rsurface.array_size < model->surfmesh.num_vertices)
9279                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9280         rsurface.matrix = identitymatrix;
9281         rsurface.inversematrix = identitymatrix;
9282         rsurface.matrixscale = 1;
9283         rsurface.inversematrixscale = 1;
9284         R_EntityMatrix(&identitymatrix);
9285         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9286         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9287         rsurface.fograngerecip = r_refdef.fograngerecip;
9288         rsurface.fogheightfade = r_refdef.fogheightfade;
9289         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9290         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9291         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9292         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9293         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9294         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9295         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9296         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9297         rsurface.colormod[3] = 1;
9298         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);
9299         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9300         rsurface.frameblend[0].lerp = 1;
9301         rsurface.ent_alttextures = false;
9302         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9303         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9304         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9305         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9306         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9307         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9308         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9309         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9310         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9311         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9312         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9313         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9314         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9315         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9316         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9317         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9318         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9319         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9320         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9321         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9322         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9323         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9324         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9325         rsurface.modelelement3i = model->surfmesh.data_element3i;
9326         rsurface.modelelement3s = model->surfmesh.data_element3s;
9327         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9328         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9329         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9330         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9331         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9332         rsurface.modelsurfaces = model->data_surfaces;
9333         rsurface.generatedvertex = false;
9334         rsurface.vertex3f  = rsurface.modelvertex3f;
9335         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9336         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9337         rsurface.svector3f = rsurface.modelsvector3f;
9338         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9339         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9340         rsurface.tvector3f = rsurface.modeltvector3f;
9341         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9342         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9343         rsurface.normal3f  = rsurface.modelnormal3f;
9344         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9345         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9346         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9347 }
9348
9349 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9350 {
9351         dp_model_t *model = ent->model;
9352         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9353         //      return;
9354         rsurface.entity = (entity_render_t *)ent;
9355         rsurface.skeleton = ent->skeleton;
9356         rsurface.ent_skinnum = ent->skinnum;
9357         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;
9358         rsurface.ent_shadertime = ent->shadertime;
9359         rsurface.ent_flags = ent->flags;
9360         if (rsurface.array_size < model->surfmesh.num_vertices)
9361                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9362         rsurface.matrix = ent->matrix;
9363         rsurface.inversematrix = ent->inversematrix;
9364         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9365         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9366         R_EntityMatrix(&rsurface.matrix);
9367         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9368         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9369         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9370         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9371         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9372         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9373         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9374         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9375         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9376         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9377         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9378         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9379         rsurface.colormod[3] = ent->alpha;
9380         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9381         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9382         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9383         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9384         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9385         if (ent->model->brush.submodel && !prepass)
9386         {
9387                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9388                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9389         }
9390         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9391         {
9392                 if (ent->animcache_vertex3f && !r_framedata_failed)
9393                 {
9394                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9395                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9396                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9397                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9398                 }
9399                 else if (wanttangents)
9400                 {
9401                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9402                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9403                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9404                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9405                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9406                 }
9407                 else if (wantnormals)
9408                 {
9409                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9410                         rsurface.modelsvector3f = NULL;
9411                         rsurface.modeltvector3f = NULL;
9412                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9413                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9414                 }
9415                 else
9416                 {
9417                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9418                         rsurface.modelsvector3f = NULL;
9419                         rsurface.modeltvector3f = NULL;
9420                         rsurface.modelnormal3f = NULL;
9421                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9422                 }
9423                 rsurface.modelvertex3f_bufferobject = 0;
9424                 rsurface.modelvertex3f_bufferoffset = 0;
9425                 rsurface.modelsvector3f_bufferobject = 0;
9426                 rsurface.modelsvector3f_bufferoffset = 0;
9427                 rsurface.modeltvector3f_bufferobject = 0;
9428                 rsurface.modeltvector3f_bufferoffset = 0;
9429                 rsurface.modelnormal3f_bufferobject = 0;
9430                 rsurface.modelnormal3f_bufferoffset = 0;
9431                 rsurface.generatedvertex = true;
9432         }
9433         else
9434         {
9435                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9436                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9437                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9438                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9439                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9440                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9441                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9442                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9443                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9444                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9445                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9446                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9447                 rsurface.generatedvertex = false;
9448         }
9449         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9450         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9451         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9452         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9453         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9454         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9455         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9456         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9457         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9458         rsurface.modelelement3i = model->surfmesh.data_element3i;
9459         rsurface.modelelement3s = model->surfmesh.data_element3s;
9460         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9461         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9462         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9463         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9464         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9465         rsurface.modelsurfaces = model->data_surfaces;
9466         rsurface.vertex3f  = rsurface.modelvertex3f;
9467         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9468         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9469         rsurface.svector3f = rsurface.modelsvector3f;
9470         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9471         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9472         rsurface.tvector3f = rsurface.modeltvector3f;
9473         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9474         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9475         rsurface.normal3f  = rsurface.modelnormal3f;
9476         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9477         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9478         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9479 }
9480
9481 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)
9482 {
9483         rsurface.entity = r_refdef.scene.worldentity;
9484         rsurface.skeleton = NULL;
9485         rsurface.ent_skinnum = 0;
9486         rsurface.ent_qwskin = -1;
9487         rsurface.ent_shadertime = shadertime;
9488         rsurface.ent_flags = entflags;
9489         rsurface.modelnum_vertices = numvertices;
9490         rsurface.modelnum_triangles = numtriangles;
9491         if (rsurface.array_size < rsurface.modelnum_vertices)
9492                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9493         rsurface.matrix = *matrix;
9494         rsurface.inversematrix = *inversematrix;
9495         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9496         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9497         R_EntityMatrix(&rsurface.matrix);
9498         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9499         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9500         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9501         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9502         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9503         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9504         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9505         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9506         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9507         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9508         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9509         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9510         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);
9511         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9512         rsurface.frameblend[0].lerp = 1;
9513         rsurface.ent_alttextures = false;
9514         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9515         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9516         if (wanttangents)
9517         {
9518                 rsurface.modelvertex3f = vertex3f;
9519                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9520                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9521                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9522         }
9523         else if (wantnormals)
9524         {
9525                 rsurface.modelvertex3f = vertex3f;
9526                 rsurface.modelsvector3f = NULL;
9527                 rsurface.modeltvector3f = NULL;
9528                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9529         }
9530         else
9531         {
9532                 rsurface.modelvertex3f = vertex3f;
9533                 rsurface.modelsvector3f = NULL;
9534                 rsurface.modeltvector3f = NULL;
9535                 rsurface.modelnormal3f = NULL;
9536         }
9537         rsurface.modelvertex3f_bufferobject = 0;
9538         rsurface.modelvertex3f_bufferoffset = 0;
9539         rsurface.modelsvector3f_bufferobject = 0;
9540         rsurface.modelsvector3f_bufferoffset = 0;
9541         rsurface.modeltvector3f_bufferobject = 0;
9542         rsurface.modeltvector3f_bufferoffset = 0;
9543         rsurface.modelnormal3f_bufferobject = 0;
9544         rsurface.modelnormal3f_bufferoffset = 0;
9545         rsurface.generatedvertex = true;
9546         rsurface.modellightmapcolor4f  = color4f;
9547         rsurface.modellightmapcolor4f_bufferobject = 0;
9548         rsurface.modellightmapcolor4f_bufferoffset = 0;
9549         rsurface.modeltexcoordtexture2f  = texcoord2f;
9550         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9551         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9552         rsurface.modeltexcoordlightmap2f  = NULL;
9553         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9554         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9555         rsurface.modelelement3i = element3i;
9556         rsurface.modelelement3s = element3s;
9557         rsurface.modelelement3i_bufferobject = 0;
9558         rsurface.modelelement3s_bufferobject = 0;
9559         rsurface.modellightmapoffsets = NULL;
9560         rsurface.modelsurfaces = NULL;
9561         rsurface.vertex3f  = rsurface.modelvertex3f;
9562         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9563         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9564         rsurface.svector3f = rsurface.modelsvector3f;
9565         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9566         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9567         rsurface.tvector3f = rsurface.modeltvector3f;
9568         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9569         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9570         rsurface.normal3f  = rsurface.modelnormal3f;
9571         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9572         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9573         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9574
9575         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9576         {
9577                 if ((wantnormals || wanttangents) && !normal3f)
9578                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9579                 if (wanttangents && !svector3f)
9580                         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);
9581         }
9582 }
9583
9584 float RSurf_FogPoint(const float *v)
9585 {
9586         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9587         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9588         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9589         float FogHeightFade = r_refdef.fogheightfade;
9590         float fogfrac;
9591         unsigned int fogmasktableindex;
9592         if (r_refdef.fogplaneviewabove)
9593                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9594         else
9595                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9596         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9597         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9598 }
9599
9600 float RSurf_FogVertex(const float *v)
9601 {
9602         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9603         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9604         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9605         float FogHeightFade = rsurface.fogheightfade;
9606         float fogfrac;
9607         unsigned int fogmasktableindex;
9608         if (r_refdef.fogplaneviewabove)
9609                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9610         else
9611                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9612         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9613         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9614 }
9615
9616 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9617 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9618 {
9619         int deformindex;
9620         int texturesurfaceindex;
9621         int i, j;
9622         float amplitude;
9623         float animpos;
9624         float scale;
9625         const float *v1, *in_tc;
9626         float *out_tc;
9627         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9628         float waveparms[4];
9629         q3shaderinfo_deform_t *deform;
9630         // 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
9631         if (rsurface.generatedvertex)
9632         {
9633                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9634                         generatenormals = true;
9635                 for (i = 0;i < Q3MAXDEFORMS;i++)
9636                 {
9637                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9638                         {
9639                                 generatetangents = true;
9640                                 generatenormals = true;
9641                         }
9642                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9643                                 generatenormals = true;
9644                 }
9645                 if (generatenormals && !rsurface.modelnormal3f)
9646                 {
9647                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9648                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9649                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9650                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9651                 }
9652                 if (generatetangents && !rsurface.modelsvector3f)
9653                 {
9654                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9655                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9656                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9657                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9658                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9659                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9660                         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);
9661                 }
9662         }
9663         rsurface.vertex3f  = rsurface.modelvertex3f;
9664         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9665         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9666         rsurface.svector3f = rsurface.modelsvector3f;
9667         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9668         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9669         rsurface.tvector3f = rsurface.modeltvector3f;
9670         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9671         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9672         rsurface.normal3f  = rsurface.modelnormal3f;
9673         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9674         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9675         // if vertices are deformed (sprite flares and things in maps, possibly
9676         // water waves, bulges and other deformations), generate them into
9677         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9678         // (may be static model data or generated data for an animated model, or
9679         //  the previous deform pass)
9680         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9681         {
9682                 switch (deform->deform)
9683                 {
9684                 default:
9685                 case Q3DEFORM_PROJECTIONSHADOW:
9686                 case Q3DEFORM_TEXT0:
9687                 case Q3DEFORM_TEXT1:
9688                 case Q3DEFORM_TEXT2:
9689                 case Q3DEFORM_TEXT3:
9690                 case Q3DEFORM_TEXT4:
9691                 case Q3DEFORM_TEXT5:
9692                 case Q3DEFORM_TEXT6:
9693                 case Q3DEFORM_TEXT7:
9694                 case Q3DEFORM_NONE:
9695                         break;
9696                 case Q3DEFORM_AUTOSPRITE:
9697                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9698                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9699                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9700                         VectorNormalize(newforward);
9701                         VectorNormalize(newright);
9702                         VectorNormalize(newup);
9703                         // make deformed versions of only the model vertices used by the specified surfaces
9704                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9705                         {
9706                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9707                                 // a single autosprite surface can contain multiple sprites...
9708                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9709                                 {
9710                                         VectorClear(center);
9711                                         for (i = 0;i < 4;i++)
9712                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9713                                         VectorScale(center, 0.25f, center);
9714                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9715                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9716                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9717                                         for (i = 0;i < 4;i++)
9718                                         {
9719                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9720                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9721                                         }
9722                                 }
9723                                 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);
9724                                 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);
9725                         }
9726                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9727                         rsurface.vertex3f_bufferobject = 0;
9728                         rsurface.vertex3f_bufferoffset = 0;
9729                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9730                         rsurface.svector3f_bufferobject = 0;
9731                         rsurface.svector3f_bufferoffset = 0;
9732                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9733                         rsurface.tvector3f_bufferobject = 0;
9734                         rsurface.tvector3f_bufferoffset = 0;
9735                         rsurface.normal3f = rsurface.array_deformednormal3f;
9736                         rsurface.normal3f_bufferobject = 0;
9737                         rsurface.normal3f_bufferoffset = 0;
9738                         break;
9739                 case Q3DEFORM_AUTOSPRITE2:
9740                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9741                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9742                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9743                         VectorNormalize(newforward);
9744                         VectorNormalize(newright);
9745                         VectorNormalize(newup);
9746                         // make deformed versions of only the model vertices used by the specified surfaces
9747                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9748                         {
9749                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9750                                 const float *v1, *v2;
9751                                 vec3_t start, end;
9752                                 float f, l;
9753                                 struct
9754                                 {
9755                                         float length2;
9756                                         const float *v1;
9757                                         const float *v2;
9758                                 }
9759                                 shortest[2];
9760                                 memset(shortest, 0, sizeof(shortest));
9761                                 // a single autosprite surface can contain multiple sprites...
9762                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9763                                 {
9764                                         VectorClear(center);
9765                                         for (i = 0;i < 4;i++)
9766                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9767                                         VectorScale(center, 0.25f, center);
9768                                         // find the two shortest edges, then use them to define the
9769                                         // axis vectors for rotating around the central axis
9770                                         for (i = 0;i < 6;i++)
9771                                         {
9772                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9773                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9774 #if 0
9775                                                 Debug_PolygonBegin(NULL, 0);
9776                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9777                                                 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);
9778                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9779                                                 Debug_PolygonEnd();
9780 #endif
9781                                                 l = VectorDistance2(v1, v2);
9782                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9783                                                 if (v1[2] != v2[2])
9784                                                         l += (1.0f / 1024.0f);
9785                                                 if (shortest[0].length2 > l || i == 0)
9786                                                 {
9787                                                         shortest[1] = shortest[0];
9788                                                         shortest[0].length2 = l;
9789                                                         shortest[0].v1 = v1;
9790                                                         shortest[0].v2 = v2;
9791                                                 }
9792                                                 else if (shortest[1].length2 > l || i == 1)
9793                                                 {
9794                                                         shortest[1].length2 = l;
9795                                                         shortest[1].v1 = v1;
9796                                                         shortest[1].v2 = v2;
9797                                                 }
9798                                         }
9799                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9800                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9801 #if 0
9802                                         Debug_PolygonBegin(NULL, 0);
9803                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9804                                         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);
9805                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9806                                         Debug_PolygonEnd();
9807 #endif
9808                                         // this calculates the right vector from the shortest edge
9809                                         // and the up vector from the edge midpoints
9810                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9811                                         VectorNormalize(right);
9812                                         VectorSubtract(end, start, up);
9813                                         VectorNormalize(up);
9814                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9815                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9816                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9817                                         VectorNegate(forward, forward);
9818                                         VectorReflect(forward, 0, up, forward);
9819                                         VectorNormalize(forward);
9820                                         CrossProduct(up, forward, newright);
9821                                         VectorNormalize(newright);
9822 #if 0
9823                                         Debug_PolygonBegin(NULL, 0);
9824                                         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);
9825                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9826                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9827                                         Debug_PolygonEnd();
9828 #endif
9829 #if 0
9830                                         Debug_PolygonBegin(NULL, 0);
9831                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9832                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9833                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9834                                         Debug_PolygonEnd();
9835 #endif
9836                                         // rotate the quad around the up axis vector, this is made
9837                                         // especially easy by the fact we know the quad is flat,
9838                                         // so we only have to subtract the center position and
9839                                         // measure distance along the right vector, and then
9840                                         // multiply that by the newright vector and add back the
9841                                         // center position
9842                                         // we also need to subtract the old position to undo the
9843                                         // displacement from the center, which we do with a
9844                                         // DotProduct, the subtraction/addition of center is also
9845                                         // optimized into DotProducts here
9846                                         l = DotProduct(right, center);
9847                                         for (i = 0;i < 4;i++)
9848                                         {
9849                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9850                                                 f = DotProduct(right, v1) - l;
9851                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9852                                         }
9853                                 }
9854                                 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);
9855                                 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);
9856                         }
9857                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9858                         rsurface.vertex3f_bufferobject = 0;
9859                         rsurface.vertex3f_bufferoffset = 0;
9860                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9861                         rsurface.svector3f_bufferobject = 0;
9862                         rsurface.svector3f_bufferoffset = 0;
9863                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9864                         rsurface.tvector3f_bufferobject = 0;
9865                         rsurface.tvector3f_bufferoffset = 0;
9866                         rsurface.normal3f = rsurface.array_deformednormal3f;
9867                         rsurface.normal3f_bufferobject = 0;
9868                         rsurface.normal3f_bufferoffset = 0;
9869                         break;
9870                 case Q3DEFORM_NORMAL:
9871                         // deform the normals to make reflections wavey
9872                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9873                         {
9874                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9875                                 for (j = 0;j < surface->num_vertices;j++)
9876                                 {
9877                                         float vertex[3];
9878                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9879                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9880                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9881                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9882                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9883                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9884                                         VectorNormalize(normal);
9885                                 }
9886                                 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);
9887                         }
9888                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9889                         rsurface.svector3f_bufferobject = 0;
9890                         rsurface.svector3f_bufferoffset = 0;
9891                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9892                         rsurface.tvector3f_bufferobject = 0;
9893                         rsurface.tvector3f_bufferoffset = 0;
9894                         rsurface.normal3f = rsurface.array_deformednormal3f;
9895                         rsurface.normal3f_bufferobject = 0;
9896                         rsurface.normal3f_bufferoffset = 0;
9897                         break;
9898                 case Q3DEFORM_WAVE:
9899                         // deform vertex array to make wavey water and flags and such
9900                         waveparms[0] = deform->waveparms[0];
9901                         waveparms[1] = deform->waveparms[1];
9902                         waveparms[2] = deform->waveparms[2];
9903                         waveparms[3] = deform->waveparms[3];
9904                         // this is how a divisor of vertex influence on deformation
9905                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9906                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9907                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9908                         {
9909                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9910                                 for (j = 0;j < surface->num_vertices;j++)
9911                                 {
9912                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9913                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9914                                         // if the wavefunc depends on time, evaluate it per-vertex
9915                                         if (waveparms[3])
9916                                         {
9917                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9918                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9919                                         }
9920                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9921                                 }
9922                         }
9923                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9924                         rsurface.vertex3f_bufferobject = 0;
9925                         rsurface.vertex3f_bufferoffset = 0;
9926                         break;
9927                 case Q3DEFORM_BULGE:
9928                         // deform vertex array to make the surface have moving bulges
9929                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9930                         {
9931                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9932                                 for (j = 0;j < surface->num_vertices;j++)
9933                                 {
9934                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9935                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9936                                 }
9937                         }
9938                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9939                         rsurface.vertex3f_bufferobject = 0;
9940                         rsurface.vertex3f_bufferoffset = 0;
9941                         break;
9942                 case Q3DEFORM_MOVE:
9943                         // deform vertex array
9944                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9945                         VectorScale(deform->parms, scale, waveparms);
9946                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9947                         {
9948                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9949                                 for (j = 0;j < surface->num_vertices;j++)
9950                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9951                         }
9952                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9953                         rsurface.vertex3f_bufferobject = 0;
9954                         rsurface.vertex3f_bufferoffset = 0;
9955                         break;
9956                 }
9957         }
9958         // generate texcoords based on the chosen texcoord source
9959         switch(rsurface.texture->tcgen.tcgen)
9960         {
9961         default:
9962         case Q3TCGEN_TEXTURE:
9963                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9964                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9965                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9966                 break;
9967         case Q3TCGEN_LIGHTMAP:
9968                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9969                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9970                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9971                 break;
9972         case Q3TCGEN_VECTOR:
9973                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9974                 {
9975                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9976                         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)
9977                         {
9978                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
9979                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
9980                         }
9981                 }
9982                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
9983                 rsurface.texcoordtexture2f_bufferobject  = 0;
9984                 rsurface.texcoordtexture2f_bufferoffset  = 0;
9985                 break;
9986         case Q3TCGEN_ENVIRONMENT:
9987                 // make environment reflections using a spheremap
9988                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9989                 {
9990                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9991                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
9992                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
9993                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
9994                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
9995                         {
9996                                 // identical to Q3A's method, but executed in worldspace so
9997                                 // carried models can be shiny too
9998
9999                                 float viewer[3], d, reflected[3], worldreflected[3];
10000
10001                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10002                                 // VectorNormalize(viewer);
10003
10004                                 d = DotProduct(normal, viewer);
10005
10006                                 reflected[0] = normal[0]*2*d - viewer[0];
10007                                 reflected[1] = normal[1]*2*d - viewer[1];
10008                                 reflected[2] = normal[2]*2*d - viewer[2];
10009                                 // note: this is proportinal to viewer, so we can normalize later
10010
10011                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10012                                 VectorNormalize(worldreflected);
10013
10014                                 // note: this sphere map only uses world x and z!
10015                                 // so positive and negative y will LOOK THE SAME.
10016                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10017                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10018                         }
10019                 }
10020                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10021                 rsurface.texcoordtexture2f_bufferobject  = 0;
10022                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10023                 break;
10024         }
10025         // the only tcmod that needs software vertex processing is turbulent, so
10026         // check for it here and apply the changes if needed
10027         // and we only support that as the first one
10028         // (handling a mixture of turbulent and other tcmods would be problematic
10029         //  without punting it entirely to a software path)
10030         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10031         {
10032                 amplitude = rsurface.texture->tcmods[0].parms[1];
10033                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10034                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10035                 {
10036                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10037                         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)
10038                         {
10039                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10040                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10041                         }
10042                 }
10043                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10044                 rsurface.texcoordtexture2f_bufferobject  = 0;
10045                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10046         }
10047         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10048         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10049         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10050         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10051 }
10052
10053 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10054 {
10055         int i, j;
10056         const msurface_t *surface = texturesurfacelist[0];
10057         const msurface_t *surface2;
10058         int firstvertex;
10059         int endvertex;
10060         int numvertices;
10061         int numtriangles;
10062         // TODO: lock all array ranges before render, rather than on each surface
10063         if (texturenumsurfaces == 1)
10064                 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);
10065         else if (r_batchmode.integer == 2)
10066         {
10067                 #define MAXBATCHTRIANGLES 4096
10068                 int batchtriangles = 0;
10069                 static int batchelements[MAXBATCHTRIANGLES*3];
10070                 for (i = 0;i < texturenumsurfaces;i = j)
10071                 {
10072                         surface = texturesurfacelist[i];
10073                         j = i + 1;
10074                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10075                         {
10076                                 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);
10077                                 continue;
10078                         }
10079                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10080                         batchtriangles = surface->num_triangles;
10081                         firstvertex = surface->num_firstvertex;
10082                         endvertex = surface->num_firstvertex + surface->num_vertices;
10083                         for (;j < texturenumsurfaces;j++)
10084                         {
10085                                 surface2 = texturesurfacelist[j];
10086                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10087                                         break;
10088                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10089                                 batchtriangles += surface2->num_triangles;
10090                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10091                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10092                         }
10093                         surface2 = texturesurfacelist[j-1];
10094                         numvertices = endvertex - firstvertex;
10095                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10096                 }
10097         }
10098         else if (r_batchmode.integer == 1)
10099         {
10100                 for (i = 0;i < texturenumsurfaces;i = j)
10101                 {
10102                         surface = texturesurfacelist[i];
10103                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10104                                 if (texturesurfacelist[j] != surface2)
10105                                         break;
10106                         surface2 = texturesurfacelist[j-1];
10107                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10108                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10109                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10110                 }
10111         }
10112         else
10113         {
10114                 for (i = 0;i < texturenumsurfaces;i++)
10115                 {
10116                         surface = texturesurfacelist[i];
10117                         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);
10118                 }
10119         }
10120 }
10121
10122 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10123 {
10124         switch(vid.renderpath)
10125         {
10126         case RENDERPATH_CGGL:
10127 #ifdef SUPPORTCG
10128                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10129                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10130 #endif
10131                 break;
10132         case RENDERPATH_GL20:
10133                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10134                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10135                 break;
10136         case RENDERPATH_GL13:
10137         case RENDERPATH_GL11:
10138                 R_Mesh_TexBind(0, surface->lightmaptexture);
10139                 break;
10140         }
10141 }
10142
10143 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10144 {
10145         // pick the closest matching water plane and bind textures
10146         int planeindex, vertexindex;
10147         float d, bestd;
10148         vec3_t vert;
10149         const float *v;
10150         r_waterstate_waterplane_t *p, *bestp;
10151         bestd = 0;
10152         bestp = NULL;
10153         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10154         {
10155                 d = 0;
10156                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10157                 {
10158                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10159                         d += fabs(PlaneDiff(vert, &p->plane));
10160                 }
10161                 if (bestd > d || !bestp)
10162                 {
10163                         bestd = d;
10164                         bestp = p;
10165                 }
10166         }
10167         switch(vid.renderpath)
10168         {
10169         case RENDERPATH_CGGL:
10170 #ifdef SUPPORTCG
10171                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10172                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10173 #endif
10174                 break;
10175         case RENDERPATH_GL20:
10176                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10177                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10178                 break;
10179         case RENDERPATH_GL13:
10180         case RENDERPATH_GL11:
10181                 break;
10182         }
10183 }
10184
10185 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10186 {
10187         int i;
10188         const msurface_t *surface;
10189         if (r_waterstate.renderingscene)
10190                 return;
10191         for (i = 0;i < texturenumsurfaces;i++)
10192         {
10193                 surface = texturesurfacelist[i];
10194                 RSurf_BindLightmapForSurface(surface);
10195                 RSurf_BindReflectionForSurface(surface);
10196                 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);
10197         }
10198 }
10199
10200 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10201 {
10202         int i;
10203         int j;
10204         const msurface_t *surface = texturesurfacelist[0];
10205         const msurface_t *surface2;
10206         int firstvertex;
10207         int endvertex;
10208         int numvertices;
10209         int numtriangles;
10210         if (texturenumsurfaces == 1)
10211         {
10212                 RSurf_BindLightmapForSurface(surface);
10213                 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);
10214         }
10215         else if (r_batchmode.integer == 2)
10216         {
10217 #define MAXBATCHTRIANGLES 4096
10218                 int batchtriangles = 0;
10219                 static int batchelements[MAXBATCHTRIANGLES*3];
10220                 for (i = 0;i < texturenumsurfaces;i = j)
10221                 {
10222                         surface = texturesurfacelist[i];
10223                         RSurf_BindLightmapForSurface(surface);
10224                         j = i + 1;
10225                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10226                         {
10227                                 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);
10228                                 continue;
10229                         }
10230                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10231                         batchtriangles = surface->num_triangles;
10232                         firstvertex = surface->num_firstvertex;
10233                         endvertex = surface->num_firstvertex + surface->num_vertices;
10234                         for (;j < texturenumsurfaces;j++)
10235                         {
10236                                 surface2 = texturesurfacelist[j];
10237                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10238                                         break;
10239                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10240                                 batchtriangles += surface2->num_triangles;
10241                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10242                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10243                         }
10244                         surface2 = texturesurfacelist[j-1];
10245                         numvertices = endvertex - firstvertex;
10246                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10247                 }
10248         }
10249         else if (r_batchmode.integer == 1)
10250         {
10251 #if 0
10252                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10253                 for (i = 0;i < texturenumsurfaces;i = j)
10254                 {
10255                         surface = texturesurfacelist[i];
10256                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10257                                 if (texturesurfacelist[j] != surface2)
10258                                         break;
10259                         Con_Printf(" %i", j - i);
10260                 }
10261                 Con_Printf("\n");
10262                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10263 #endif
10264                 for (i = 0;i < texturenumsurfaces;i = j)
10265                 {
10266                         surface = texturesurfacelist[i];
10267                         RSurf_BindLightmapForSurface(surface);
10268                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10269                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10270                                         break;
10271 #if 0
10272                         Con_Printf(" %i", j - i);
10273 #endif
10274                         surface2 = texturesurfacelist[j-1];
10275                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10276                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10277                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10278                 }
10279 #if 0
10280                 Con_Printf("\n");
10281 #endif
10282         }
10283         else
10284         {
10285                 for (i = 0;i < texturenumsurfaces;i++)
10286                 {
10287                         surface = texturesurfacelist[i];
10288                         RSurf_BindLightmapForSurface(surface);
10289                         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);
10290                 }
10291         }
10292 }
10293
10294 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10295 {
10296         int j;
10297         int texturesurfaceindex;
10298         if (r_showsurfaces.integer == 2)
10299         {
10300                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10301                 {
10302                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10303                         for (j = 0;j < surface->num_triangles;j++)
10304                         {
10305                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10306                                 GL_Color(f, f, f, 1);
10307                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10308                         }
10309                 }
10310         }
10311         else
10312         {
10313                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10314                 {
10315                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10316                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10317                         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);
10318                         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);
10319                 }
10320         }
10321 }
10322
10323 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10324 {
10325         int texturesurfaceindex;
10326         int i;
10327         const float *v;
10328         float *c2;
10329         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10330         {
10331                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10332                 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)
10333                 {
10334                         c2[0] = 0.5;
10335                         c2[1] = 0.5;
10336                         c2[2] = 0.5;
10337                         c2[3] = 1;
10338                 }
10339         }
10340         rsurface.lightmapcolor4f = rsurface.array_color4f;
10341         rsurface.lightmapcolor4f_bufferobject = 0;
10342         rsurface.lightmapcolor4f_bufferoffset = 0;
10343 }
10344
10345 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10346 {
10347         int texturesurfaceindex;
10348         int i;
10349         float f;
10350         const float *v;
10351         const float *c;
10352         float *c2;
10353         if (rsurface.lightmapcolor4f)
10354         {
10355                 // generate color arrays for the surfaces in this list
10356                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10357                 {
10358                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10359                         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)
10360                         {
10361                                 f = RSurf_FogVertex(v);
10362                                 c2[0] = c[0] * f;
10363                                 c2[1] = c[1] * f;
10364                                 c2[2] = c[2] * f;
10365                                 c2[3] = c[3];
10366                         }
10367                 }
10368         }
10369         else
10370         {
10371                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10372                 {
10373                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10374                         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)
10375                         {
10376                                 f = RSurf_FogVertex(v);
10377                                 c2[0] = f;
10378                                 c2[1] = f;
10379                                 c2[2] = f;
10380                                 c2[3] = 1;
10381                         }
10382                 }
10383         }
10384         rsurface.lightmapcolor4f = rsurface.array_color4f;
10385         rsurface.lightmapcolor4f_bufferobject = 0;
10386         rsurface.lightmapcolor4f_bufferoffset = 0;
10387 }
10388
10389 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10390 {
10391         int texturesurfaceindex;
10392         int i;
10393         float f;
10394         const float *v;
10395         const float *c;
10396         float *c2;
10397         if (!rsurface.lightmapcolor4f)
10398                 return;
10399         // generate color arrays for the surfaces in this list
10400         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10401         {
10402                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10403                 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)
10404                 {
10405                         f = RSurf_FogVertex(v);
10406                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10407                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10408                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10409                         c2[3] = c[3];
10410                 }
10411         }
10412         rsurface.lightmapcolor4f = rsurface.array_color4f;
10413         rsurface.lightmapcolor4f_bufferobject = 0;
10414         rsurface.lightmapcolor4f_bufferoffset = 0;
10415 }
10416
10417 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10418 {
10419         int texturesurfaceindex;
10420         int i;
10421         const float *c;
10422         float *c2;
10423         if (!rsurface.lightmapcolor4f)
10424                 return;
10425         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10426         {
10427                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10428                 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)
10429                 {
10430                         c2[0] = c[0] * r;
10431                         c2[1] = c[1] * g;
10432                         c2[2] = c[2] * b;
10433                         c2[3] = c[3] * a;
10434                 }
10435         }
10436         rsurface.lightmapcolor4f = rsurface.array_color4f;
10437         rsurface.lightmapcolor4f_bufferobject = 0;
10438         rsurface.lightmapcolor4f_bufferoffset = 0;
10439 }
10440
10441 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10442 {
10443         int texturesurfaceindex;
10444         int i;
10445         const float *c;
10446         float *c2;
10447         if (!rsurface.lightmapcolor4f)
10448                 return;
10449         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10450         {
10451                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10452                 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)
10453                 {
10454                         c2[0] = c[0] + r_refdef.scene.ambient;
10455                         c2[1] = c[1] + r_refdef.scene.ambient;
10456                         c2[2] = c[2] + r_refdef.scene.ambient;
10457                         c2[3] = c[3];
10458                 }
10459         }
10460         rsurface.lightmapcolor4f = rsurface.array_color4f;
10461         rsurface.lightmapcolor4f_bufferobject = 0;
10462         rsurface.lightmapcolor4f_bufferoffset = 0;
10463 }
10464
10465 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10466 {
10467         // TODO: optimize
10468         rsurface.lightmapcolor4f = NULL;
10469         rsurface.lightmapcolor4f_bufferobject = 0;
10470         rsurface.lightmapcolor4f_bufferoffset = 0;
10471         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10472         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10473         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10474         GL_Color(r, g, b, a);
10475         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10476 }
10477
10478 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10479 {
10480         // TODO: optimize applyfog && applycolor case
10481         // just apply fog if necessary, and tint the fog color array if necessary
10482         rsurface.lightmapcolor4f = NULL;
10483         rsurface.lightmapcolor4f_bufferobject = 0;
10484         rsurface.lightmapcolor4f_bufferoffset = 0;
10485         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10486         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10487         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10488         GL_Color(r, g, b, a);
10489         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10490 }
10491
10492 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10493 {
10494         int texturesurfaceindex;
10495         int i;
10496         float *c;
10497         // TODO: optimize
10498         if (texturesurfacelist[0]->lightmapinfo)
10499         {
10500                 // generate color arrays for the surfaces in this list
10501                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10502                 {
10503                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10504                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10505                         {
10506                                 if (surface->lightmapinfo->samples)
10507                                 {
10508                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10509                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10510                                         VectorScale(lm, scale, c);
10511                                         if (surface->lightmapinfo->styles[1] != 255)
10512                                         {
10513                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10514                                                 lm += size3;
10515                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10516                                                 VectorMA(c, scale, lm, c);
10517                                                 if (surface->lightmapinfo->styles[2] != 255)
10518                                                 {
10519                                                         lm += size3;
10520                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10521                                                         VectorMA(c, scale, lm, c);
10522                                                         if (surface->lightmapinfo->styles[3] != 255)
10523                                                         {
10524                                                                 lm += size3;
10525                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10526                                                                 VectorMA(c, scale, lm, c);
10527                                                         }
10528                                                 }
10529                                         }
10530                                 }
10531                                 else
10532                                         VectorClear(c);
10533                                 c[3] = 1;
10534                         }
10535                 }
10536                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10537                 rsurface.lightmapcolor4f_bufferobject = 0;
10538                 rsurface.lightmapcolor4f_bufferoffset = 0;
10539         }
10540         else
10541         {
10542                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10543                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10544                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10545         }
10546         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10547         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10548         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10549         GL_Color(r, g, b, a);
10550         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10551 }
10552
10553 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10554 {
10555         int texturesurfaceindex;
10556         int i;
10557         float f;
10558         float alpha;
10559         const float *v;
10560         const float *n;
10561         float *c;
10562         vec3_t ambientcolor;
10563         vec3_t diffusecolor;
10564         vec3_t lightdir;
10565         // TODO: optimize
10566         // model lighting
10567         VectorCopy(rsurface.modellight_lightdir, lightdir);
10568         f = 0.5f * r_refdef.lightmapintensity;
10569         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10570         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10571         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10572         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10573         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10574         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10575         alpha = *a;
10576         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10577         {
10578                 // generate color arrays for the surfaces in this list
10579                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10580                 {
10581                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10582                         int numverts = surface->num_vertices;
10583                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10584                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10585                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10586                         // q3-style directional shading
10587                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10588                         {
10589                                 if ((f = DotProduct(n, lightdir)) > 0)
10590                                         VectorMA(ambientcolor, f, diffusecolor, c);
10591                                 else
10592                                         VectorCopy(ambientcolor, c);
10593                                 c[3] = alpha;
10594                         }
10595                 }
10596                 *r = 1;
10597                 *g = 1;
10598                 *b = 1;
10599                 *a = 1;
10600                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10601                 rsurface.lightmapcolor4f_bufferobject = 0;
10602                 rsurface.lightmapcolor4f_bufferoffset = 0;
10603                 *applycolor = false;
10604         }
10605         else
10606         {
10607                 *r = ambientcolor[0];
10608                 *g = ambientcolor[1];
10609                 *b = ambientcolor[2];
10610                 rsurface.lightmapcolor4f = NULL;
10611                 rsurface.lightmapcolor4f_bufferobject = 0;
10612                 rsurface.lightmapcolor4f_bufferoffset = 0;
10613         }
10614 }
10615
10616 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10617 {
10618         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10619         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10620         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10621         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10622         GL_Color(r, g, b, a);
10623         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10624 }
10625
10626 void RSurf_SetupDepthAndCulling(void)
10627 {
10628         // submodels are biased to avoid z-fighting with world surfaces that they
10629         // may be exactly overlapping (avoids z-fighting artifacts on certain
10630         // doors and things in Quake maps)
10631         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10632         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10633         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10634         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10635 }
10636
10637 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10638 {
10639         // transparent sky would be ridiculous
10640         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10641                 return;
10642         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10643         skyrenderlater = true;
10644         RSurf_SetupDepthAndCulling();
10645         GL_DepthMask(true);
10646         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10647         // skymasking on them, and Quake3 never did sky masking (unlike
10648         // software Quake and software Quake2), so disable the sky masking
10649         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10650         // and skymasking also looks very bad when noclipping outside the
10651         // level, so don't use it then either.
10652         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10653         {
10654                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10655                 R_Mesh_ColorPointer(NULL, 0, 0);
10656                 R_Mesh_ResetTextureState();
10657                 if (skyrendermasked)
10658                 {
10659                         R_SetupShader_DepthOrShadow();
10660                         // depth-only (masking)
10661                         GL_ColorMask(0,0,0,0);
10662                         // just to make sure that braindead drivers don't draw
10663                         // anything despite that colormask...
10664                         GL_BlendFunc(GL_ZERO, GL_ONE);
10665                 }
10666                 else
10667                 {
10668                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10669                         // fog sky
10670                         GL_BlendFunc(GL_ONE, GL_ZERO);
10671                 }
10672                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10673                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10674                 if (skyrendermasked)
10675                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10676         }
10677         R_Mesh_ResetTextureState();
10678         GL_Color(1, 1, 1, 1);
10679 }
10680
10681 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10682 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10683 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10684 {
10685         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10686                 return;
10687         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10688         if (prepass)
10689         {
10690                 // render screenspace normalmap to texture
10691                 GL_DepthMask(true);
10692                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10693                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10694         }
10695         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10696         {
10697                 // render water or distortion background, then blend surface on top
10698                 GL_DepthMask(true);
10699                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10700                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10701                 GL_DepthMask(false);
10702                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10703                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10704                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10705                 else
10706                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10707         }
10708         else
10709         {
10710                 // render surface normally
10711                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10712                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10713                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10714                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10715                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10716                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10717                 else
10718                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10719         }
10720 }
10721
10722 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10723 {
10724         // OpenGL 1.3 path - anything not completely ancient
10725         int texturesurfaceindex;
10726         qboolean applycolor;
10727         qboolean applyfog;
10728         int layerindex;
10729         const texturelayer_t *layer;
10730         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10731
10732         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10733         {
10734                 vec4_t layercolor;
10735                 int layertexrgbscale;
10736                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10737                 {
10738                         if (layerindex == 0)
10739                                 GL_AlphaTest(true);
10740                         else
10741                         {
10742                                 GL_AlphaTest(false);
10743                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10744                         }
10745                 }
10746                 GL_DepthMask(layer->depthmask && writedepth);
10747                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10748                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10749                 {
10750                         layertexrgbscale = 4;
10751                         VectorScale(layer->color, 0.25f, layercolor);
10752                 }
10753                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10754                 {
10755                         layertexrgbscale = 2;
10756                         VectorScale(layer->color, 0.5f, layercolor);
10757                 }
10758                 else
10759                 {
10760                         layertexrgbscale = 1;
10761                         VectorScale(layer->color, 1.0f, layercolor);
10762                 }
10763                 layercolor[3] = layer->color[3];
10764                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10765                 R_Mesh_ColorPointer(NULL, 0, 0);
10766                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10767                 switch (layer->type)
10768                 {
10769                 case TEXTURELAYERTYPE_LITTEXTURE:
10770                         // single-pass lightmapped texture with 2x rgbscale
10771                         R_Mesh_TexBind(0, r_texture_white);
10772                         R_Mesh_TexMatrix(0, NULL);
10773                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10774                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10775                         R_Mesh_TexBind(1, layer->texture);
10776                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10777                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10778                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10779                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10780                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10781                         else if (rsurface.uselightmaptexture)
10782                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10783                         else
10784                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10785                         break;
10786                 case TEXTURELAYERTYPE_TEXTURE:
10787                         // singletexture unlit texture with transparency support
10788                         R_Mesh_TexBind(0, layer->texture);
10789                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10790                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10791                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10792                         R_Mesh_TexBind(1, 0);
10793                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10794                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10795                         break;
10796                 case TEXTURELAYERTYPE_FOG:
10797                         // singletexture fogging
10798                         if (layer->texture)
10799                         {
10800                                 R_Mesh_TexBind(0, layer->texture);
10801                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10802                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10803                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10804                         }
10805                         else
10806                         {
10807                                 R_Mesh_TexBind(0, 0);
10808                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10809                         }
10810                         R_Mesh_TexBind(1, 0);
10811                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10812                         // generate a color array for the fog pass
10813                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10814                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10815                         {
10816                                 int i;
10817                                 float f;
10818                                 const float *v;
10819                                 float *c;
10820                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10821                                 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)
10822                                 {
10823                                         f = 1 - RSurf_FogVertex(v);
10824                                         c[0] = layercolor[0];
10825                                         c[1] = layercolor[1];
10826                                         c[2] = layercolor[2];
10827                                         c[3] = f * layercolor[3];
10828                                 }
10829                         }
10830                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10831                         break;
10832                 default:
10833                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10834                 }
10835         }
10836         CHECKGLERROR
10837         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10838         {
10839                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10840                 GL_AlphaTest(false);
10841         }
10842 }
10843
10844 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10845 {
10846         // OpenGL 1.1 - crusty old voodoo path
10847         int texturesurfaceindex;
10848         qboolean applyfog;
10849         int layerindex;
10850         const texturelayer_t *layer;
10851         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10852
10853         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10854         {
10855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10856                 {
10857                         if (layerindex == 0)
10858                                 GL_AlphaTest(true);
10859                         else
10860                         {
10861                                 GL_AlphaTest(false);
10862                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10863                         }
10864                 }
10865                 GL_DepthMask(layer->depthmask && writedepth);
10866                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10867                 R_Mesh_ColorPointer(NULL, 0, 0);
10868                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10869                 switch (layer->type)
10870                 {
10871                 case TEXTURELAYERTYPE_LITTEXTURE:
10872                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10873                         {
10874                                 // two-pass lit texture with 2x rgbscale
10875                                 // first the lightmap pass
10876                                 R_Mesh_TexBind(0, r_texture_white);
10877                                 R_Mesh_TexMatrix(0, NULL);
10878                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10879                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10880                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10881                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10882                                 else if (rsurface.uselightmaptexture)
10883                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10884                                 else
10885                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10886                                 // then apply the texture to it
10887                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10888                                 R_Mesh_TexBind(0, layer->texture);
10889                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10890                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10891                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10892                                 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);
10893                         }
10894                         else
10895                         {
10896                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10897                                 R_Mesh_TexBind(0, layer->texture);
10898                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10899                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10900                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10901                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10902                                         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);
10903                                 else
10904                                         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);
10905                         }
10906                         break;
10907                 case TEXTURELAYERTYPE_TEXTURE:
10908                         // singletexture unlit texture with transparency support
10909                         R_Mesh_TexBind(0, layer->texture);
10910                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10911                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10912                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10913                         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);
10914                         break;
10915                 case TEXTURELAYERTYPE_FOG:
10916                         // singletexture fogging
10917                         if (layer->texture)
10918                         {
10919                                 R_Mesh_TexBind(0, layer->texture);
10920                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10921                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10922                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10923                         }
10924                         else
10925                         {
10926                                 R_Mesh_TexBind(0, 0);
10927                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10928                         }
10929                         // generate a color array for the fog pass
10930                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10931                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10932                         {
10933                                 int i;
10934                                 float f;
10935                                 const float *v;
10936                                 float *c;
10937                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10938                                 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)
10939                                 {
10940                                         f = 1 - RSurf_FogVertex(v);
10941                                         c[0] = layer->color[0];
10942                                         c[1] = layer->color[1];
10943                                         c[2] = layer->color[2];
10944                                         c[3] = f * layer->color[3];
10945                                 }
10946                         }
10947                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10948                         break;
10949                 default:
10950                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10951                 }
10952         }
10953         CHECKGLERROR
10954         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10955         {
10956                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10957                 GL_AlphaTest(false);
10958         }
10959 }
10960
10961 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10962 {
10963         float c[4];
10964
10965         GL_AlphaTest(false);
10966         R_Mesh_ColorPointer(NULL, 0, 0);
10967         R_Mesh_ResetTextureState();
10968         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10969
10970         if(rsurface.texture && rsurface.texture->currentskinframe)
10971         {
10972                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10973                 c[3] *= rsurface.texture->currentalpha;
10974         }
10975         else
10976         {
10977                 c[0] = 1;
10978                 c[1] = 0;
10979                 c[2] = 1;
10980                 c[3] = 1;
10981         }
10982
10983         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10984         {
10985                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10986                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10987                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10988         }
10989
10990         // brighten it up (as texture value 127 means "unlit")
10991         c[0] *= 2 * r_refdef.view.colorscale;
10992         c[1] *= 2 * r_refdef.view.colorscale;
10993         c[2] *= 2 * r_refdef.view.colorscale;
10994
10995         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10996                 c[3] *= r_wateralpha.value;
10997
10998         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10999         {
11000                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11001                 GL_DepthMask(false);
11002         }
11003         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11004         {
11005                 GL_BlendFunc(GL_ONE, GL_ONE);
11006                 GL_DepthMask(false);
11007         }
11008         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11009         {
11010                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11011                 GL_DepthMask(false);
11012         }
11013         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11014         {
11015                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11016                 GL_DepthMask(false);
11017         }
11018         else
11019         {
11020                 GL_BlendFunc(GL_ONE, GL_ZERO);
11021                 GL_DepthMask(writedepth);
11022         }
11023
11024         rsurface.lightmapcolor4f = NULL;
11025
11026         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11027         {
11028                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11029
11030                 rsurface.lightmapcolor4f = NULL;
11031                 rsurface.lightmapcolor4f_bufferobject = 0;
11032                 rsurface.lightmapcolor4f_bufferoffset = 0;
11033         }
11034         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11035         {
11036                 qboolean applycolor = true;
11037                 float one = 1.0;
11038
11039                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11040
11041                 r_refdef.lightmapintensity = 1;
11042                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11043                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11044         }
11045         else
11046         {
11047                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11048
11049                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11050                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11051                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11052         }
11053
11054         if(!rsurface.lightmapcolor4f)
11055                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11056
11057         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11058         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11059         if(r_refdef.fogenabled)
11060                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11061
11062         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11063         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11064 }
11065
11066 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11067 {
11068         CHECKGLERROR
11069         RSurf_SetupDepthAndCulling();
11070         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11071         {
11072                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11073                 return;
11074         }
11075         switch (vid.renderpath)
11076         {
11077         case RENDERPATH_GL20:
11078         case RENDERPATH_CGGL:
11079                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11080                 break;
11081         case RENDERPATH_GL13:
11082                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11083                 break;
11084         case RENDERPATH_GL11:
11085                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11086                 break;
11087         }
11088         CHECKGLERROR
11089 }
11090
11091 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11092 {
11093         CHECKGLERROR
11094         RSurf_SetupDepthAndCulling();
11095         if (r_showsurfaces.integer == 3 && !prepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11096         {
11097                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11098                 return;
11099         }
11100         switch (vid.renderpath)
11101         {
11102         case RENDERPATH_GL20:
11103         case RENDERPATH_CGGL:
11104                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11105                 break;
11106         case RENDERPATH_GL13:
11107                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11108                 break;
11109         case RENDERPATH_GL11:
11110                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11111                 break;
11112         }
11113         CHECKGLERROR
11114 }
11115
11116 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11117 {
11118         int i, j;
11119         int texturenumsurfaces, endsurface;
11120         texture_t *texture;
11121         const msurface_t *surface;
11122         const msurface_t *texturesurfacelist[256];
11123
11124         // if the model is static it doesn't matter what value we give for
11125         // wantnormals and wanttangents, so this logic uses only rules applicable
11126         // to a model, knowing that they are meaningless otherwise
11127         if (ent == r_refdef.scene.worldentity)
11128                 RSurf_ActiveWorldEntity();
11129         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11130                 RSurf_ActiveModelEntity(ent, false, false, false);
11131         else
11132         {
11133                 switch (vid.renderpath)
11134                 {
11135                 case RENDERPATH_GL20:
11136                 case RENDERPATH_CGGL:
11137                         RSurf_ActiveModelEntity(ent, true, true, false);
11138                         break;
11139                 case RENDERPATH_GL13:
11140                 case RENDERPATH_GL11:
11141                         RSurf_ActiveModelEntity(ent, true, false, false);
11142                         break;
11143                 }
11144         }
11145
11146         if (r_transparentdepthmasking.integer)
11147         {
11148                 qboolean setup = false;
11149                 for (i = 0;i < numsurfaces;i = j)
11150                 {
11151                         j = i + 1;
11152                         surface = rsurface.modelsurfaces + surfacelist[i];
11153                         texture = surface->texture;
11154                         rsurface.texture = R_GetCurrentTexture(texture);
11155                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11156                         // scan ahead until we find a different texture
11157                         endsurface = min(i + 1024, numsurfaces);
11158                         texturenumsurfaces = 0;
11159                         texturesurfacelist[texturenumsurfaces++] = surface;
11160                         for (;j < endsurface;j++)
11161                         {
11162                                 surface = rsurface.modelsurfaces + surfacelist[j];
11163                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11164                                         break;
11165                                 texturesurfacelist[texturenumsurfaces++] = surface;
11166                         }
11167                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11168                                 continue;
11169                         // render the range of surfaces as depth
11170                         if (!setup)
11171                         {
11172                                 setup = true;
11173                                 GL_ColorMask(0,0,0,0);
11174                                 GL_Color(1,1,1,1);
11175                                 GL_DepthTest(true);
11176                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11177                                 GL_DepthMask(true);
11178                                 GL_AlphaTest(false);
11179                                 R_Mesh_ColorPointer(NULL, 0, 0);
11180                                 R_Mesh_ResetTextureState();
11181                                 R_SetupShader_DepthOrShadow();
11182                         }
11183                         RSurf_SetupDepthAndCulling();
11184                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11185                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11186                 }
11187                 if (setup)
11188                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11189         }
11190
11191         for (i = 0;i < numsurfaces;i = j)
11192         {
11193                 j = i + 1;
11194                 surface = rsurface.modelsurfaces + surfacelist[i];
11195                 texture = surface->texture;
11196                 rsurface.texture = R_GetCurrentTexture(texture);
11197                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11198                 // scan ahead until we find a different texture
11199                 endsurface = min(i + 1024, numsurfaces);
11200                 texturenumsurfaces = 0;
11201                 texturesurfacelist[texturenumsurfaces++] = surface;
11202                 for (;j < endsurface;j++)
11203                 {
11204                         surface = rsurface.modelsurfaces + surfacelist[j];
11205                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11206                                 break;
11207                         texturesurfacelist[texturenumsurfaces++] = surface;
11208                 }
11209                 // render the range of surfaces
11210                 if (ent == r_refdef.scene.worldentity)
11211                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11212                 else
11213                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11214         }
11215         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11216         GL_AlphaTest(false);
11217 }
11218
11219 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11220 {
11221         // transparent surfaces get pushed off into the transparent queue
11222         int surfacelistindex;
11223         const msurface_t *surface;
11224         vec3_t tempcenter, center;
11225         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11226         {
11227                 surface = texturesurfacelist[surfacelistindex];
11228                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11229                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11230                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11231                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11232                 if (queueentity->transparent_offset) // transparent offset
11233                 {
11234                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11235                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11236                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11237                 }
11238                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11239         }
11240 }
11241
11242 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11243 {
11244         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11245         CHECKGLERROR
11246         if (depthonly)
11247         {
11248                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11249                         return;
11250                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11251                         return;
11252                 RSurf_SetupDepthAndCulling();
11253                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11254                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11255         }
11256         else if (prepass)
11257         {
11258                 if (!rsurface.texture->currentnumlayers)
11259                         return;
11260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11261                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11262                 else
11263                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11264         }
11265         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11266         {
11267                 RSurf_SetupDepthAndCulling();
11268                 GL_AlphaTest(false);
11269                 R_Mesh_ColorPointer(NULL, 0, 0);
11270                 R_Mesh_ResetTextureState();
11271                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11272                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11273                 GL_DepthMask(true);
11274                 GL_BlendFunc(GL_ONE, GL_ZERO);
11275                 GL_Color(0, 0, 0, 1);
11276                 GL_DepthTest(writedepth);
11277                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11278         }
11279         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11280         {
11281                 RSurf_SetupDepthAndCulling();
11282                 GL_AlphaTest(false);
11283                 R_Mesh_ColorPointer(NULL, 0, 0);
11284                 R_Mesh_ResetTextureState();
11285                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11286                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11287                 GL_DepthMask(true);
11288                 GL_BlendFunc(GL_ONE, GL_ZERO);
11289                 GL_DepthTest(true);
11290                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11291         }
11292         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11293                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11294         else if (!rsurface.texture->currentnumlayers)
11295                 return;
11296         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11297         {
11298                 // in the deferred case, transparent surfaces were queued during prepass
11299                 if (!r_shadow_usingdeferredprepass)
11300                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11301         }
11302         else
11303         {
11304                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11305                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11306         }
11307         CHECKGLERROR
11308 }
11309
11310 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11311 {
11312         int i, j;
11313         texture_t *texture;
11314         // break the surface list down into batches by texture and use of lightmapping
11315         for (i = 0;i < numsurfaces;i = j)
11316         {
11317                 j = i + 1;
11318                 // texture is the base texture pointer, rsurface.texture is the
11319                 // current frame/skin the texture is directing us to use (for example
11320                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11321                 // use skin 1 instead)
11322                 texture = surfacelist[i]->texture;
11323                 rsurface.texture = R_GetCurrentTexture(texture);
11324                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11325                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11326                 {
11327                         // if this texture is not the kind we want, skip ahead to the next one
11328                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11329                                 ;
11330                         continue;
11331                 }
11332                 // simply scan ahead until we find a different texture or lightmap state
11333                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11334                         ;
11335                 // render the range of surfaces
11336                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11337         }
11338 }
11339
11340 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11341 {
11342         CHECKGLERROR
11343         if (depthonly)
11344         {
11345                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11346                         return;
11347                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11348                         return;
11349                 RSurf_SetupDepthAndCulling();
11350                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11351                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11352         }
11353         else if (prepass)
11354         {
11355                 if (!rsurface.texture->currentnumlayers)
11356                         return;
11357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11358                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11359                 else
11360                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11361         }
11362         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11363         {
11364                 RSurf_SetupDepthAndCulling();
11365                 GL_AlphaTest(false);
11366                 R_Mesh_ColorPointer(NULL, 0, 0);
11367                 R_Mesh_ResetTextureState();
11368                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11369                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11370                 GL_DepthMask(true);
11371                 GL_BlendFunc(GL_ONE, GL_ZERO);
11372                 GL_Color(0, 0, 0, 1);
11373                 GL_DepthTest(writedepth);
11374                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11375         }
11376         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11377         {
11378                 RSurf_SetupDepthAndCulling();
11379                 GL_AlphaTest(false);
11380                 R_Mesh_ColorPointer(NULL, 0, 0);
11381                 R_Mesh_ResetTextureState();
11382                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11383                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11384                 GL_DepthMask(true);
11385                 GL_BlendFunc(GL_ONE, GL_ZERO);
11386                 GL_DepthTest(true);
11387                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11388         }
11389         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11390                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11391         else if (!rsurface.texture->currentnumlayers)
11392                 return;
11393         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11394         {
11395                 // in the deferred case, transparent surfaces were queued during prepass
11396                 if (!r_shadow_usingdeferredprepass)
11397                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11398         }
11399         else
11400         {
11401                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11402                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11403         }
11404         CHECKGLERROR
11405 }
11406
11407 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11408 {
11409         int i, j;
11410         texture_t *texture;
11411         // break the surface list down into batches by texture and use of lightmapping
11412         for (i = 0;i < numsurfaces;i = j)
11413         {
11414                 j = i + 1;
11415                 // texture is the base texture pointer, rsurface.texture is the
11416                 // current frame/skin the texture is directing us to use (for example
11417                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11418                 // use skin 1 instead)
11419                 texture = surfacelist[i]->texture;
11420                 rsurface.texture = R_GetCurrentTexture(texture);
11421                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11422                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11423                 {
11424                         // if this texture is not the kind we want, skip ahead to the next one
11425                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11426                                 ;
11427                         continue;
11428                 }
11429                 // simply scan ahead until we find a different texture or lightmap state
11430                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11431                         ;
11432                 // render the range of surfaces
11433                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11434         }
11435 }
11436
11437 float locboxvertex3f[6*4*3] =
11438 {
11439         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11440         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11441         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11442         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11443         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11444         1,0,0, 0,0,0, 0,1,0, 1,1,0
11445 };
11446
11447 unsigned short locboxelements[6*2*3] =
11448 {
11449          0, 1, 2, 0, 2, 3,
11450          4, 5, 6, 4, 6, 7,
11451          8, 9,10, 8,10,11,
11452         12,13,14, 12,14,15,
11453         16,17,18, 16,18,19,
11454         20,21,22, 20,22,23
11455 };
11456
11457 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11458 {
11459         int i, j;
11460         cl_locnode_t *loc = (cl_locnode_t *)ent;
11461         vec3_t mins, size;
11462         float vertex3f[6*4*3];
11463         CHECKGLERROR
11464         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11465         GL_DepthMask(false);
11466         GL_DepthRange(0, 1);
11467         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11468         GL_DepthTest(true);
11469         GL_CullFace(GL_NONE);
11470         R_EntityMatrix(&identitymatrix);
11471
11472         R_Mesh_VertexPointer(vertex3f, 0, 0);
11473         R_Mesh_ColorPointer(NULL, 0, 0);
11474         R_Mesh_ResetTextureState();
11475         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11476
11477         i = surfacelist[0];
11478         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11479                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11480                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11481                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11482
11483         if (VectorCompare(loc->mins, loc->maxs))
11484         {
11485                 VectorSet(size, 2, 2, 2);
11486                 VectorMA(loc->mins, -0.5f, size, mins);
11487         }
11488         else
11489         {
11490                 VectorCopy(loc->mins, mins);
11491                 VectorSubtract(loc->maxs, loc->mins, size);
11492         }
11493
11494         for (i = 0;i < 6*4*3;)
11495                 for (j = 0;j < 3;j++, i++)
11496                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11497
11498         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11499 }
11500
11501 void R_DrawLocs(void)
11502 {
11503         int index;
11504         cl_locnode_t *loc, *nearestloc;
11505         vec3_t center;
11506         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11507         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11508         {
11509                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11510                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11511         }
11512 }
11513
11514 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11515 {
11516         if (decalsystem->decals)
11517                 Mem_Free(decalsystem->decals);
11518         memset(decalsystem, 0, sizeof(*decalsystem));
11519 }
11520
11521 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)
11522 {
11523         tridecal_t *decal;
11524         tridecal_t *decals;
11525         int i;
11526
11527         // expand or initialize the system
11528         if (decalsystem->maxdecals <= decalsystem->numdecals)
11529         {
11530                 decalsystem_t old = *decalsystem;
11531                 qboolean useshortelements;
11532                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11533                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11534                 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)));
11535                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11536                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11537                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11538                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11539                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11540                 if (decalsystem->numdecals)
11541                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11542                 if (old.decals)
11543                         Mem_Free(old.decals);
11544                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11545                         decalsystem->element3i[i] = i;
11546                 if (useshortelements)
11547                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11548                                 decalsystem->element3s[i] = i;
11549         }
11550
11551         // grab a decal and search for another free slot for the next one
11552         decals = decalsystem->decals;
11553         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11554         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11555                 ;
11556         decalsystem->freedecal = i;
11557         if (decalsystem->numdecals <= i)
11558                 decalsystem->numdecals = i + 1;
11559
11560         // initialize the decal
11561         decal->lived = 0;
11562         decal->triangleindex = triangleindex;
11563         decal->surfaceindex = surfaceindex;
11564         decal->decalsequence = decalsequence;
11565         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11566         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11567         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11568         decal->color4ub[0][3] = 255;
11569         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11570         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11571         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11572         decal->color4ub[1][3] = 255;
11573         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11574         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11575         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11576         decal->color4ub[2][3] = 255;
11577         decal->vertex3f[0][0] = v0[0];
11578         decal->vertex3f[0][1] = v0[1];
11579         decal->vertex3f[0][2] = v0[2];
11580         decal->vertex3f[1][0] = v1[0];
11581         decal->vertex3f[1][1] = v1[1];
11582         decal->vertex3f[1][2] = v1[2];
11583         decal->vertex3f[2][0] = v2[0];
11584         decal->vertex3f[2][1] = v2[1];
11585         decal->vertex3f[2][2] = v2[2];
11586         decal->texcoord2f[0][0] = t0[0];
11587         decal->texcoord2f[0][1] = t0[1];
11588         decal->texcoord2f[1][0] = t1[0];
11589         decal->texcoord2f[1][1] = t1[1];
11590         decal->texcoord2f[2][0] = t2[0];
11591         decal->texcoord2f[2][1] = t2[1];
11592 }
11593
11594 extern cvar_t cl_decals_bias;
11595 extern cvar_t cl_decals_models;
11596 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11597 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)
11598 {
11599         matrix4x4_t projection;
11600         decalsystem_t *decalsystem;
11601         qboolean dynamic;
11602         dp_model_t *model;
11603         const float *vertex3f;
11604         const msurface_t *surface;
11605         const msurface_t *surfaces;
11606         const int *surfacelist;
11607         const texture_t *texture;
11608         int numtriangles;
11609         int numsurfacelist;
11610         int surfacelistindex;
11611         int surfaceindex;
11612         int triangleindex;
11613         int cornerindex;
11614         int index;
11615         int numpoints;
11616         const int *e;
11617         float localorigin[3];
11618         float localnormal[3];
11619         float localmins[3];
11620         float localmaxs[3];
11621         float localsize;
11622         float v[9][3];
11623         float tc[9][2];
11624         float c[9][4];
11625         //float normal[3];
11626         float planes[6][4];
11627         float f;
11628         float points[2][9][3];
11629         float angles[3];
11630         float temp[3];
11631
11632         decalsystem = &ent->decalsystem;
11633         model = ent->model;
11634         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11635         {
11636                 R_DecalSystem_Reset(&ent->decalsystem);
11637                 return;
11638         }
11639
11640         if (!model->brush.data_nodes && !cl_decals_models.integer)
11641         {
11642                 if (decalsystem->model)
11643                         R_DecalSystem_Reset(decalsystem);
11644                 return;
11645         }
11646
11647         if (decalsystem->model != model)
11648                 R_DecalSystem_Reset(decalsystem);
11649         decalsystem->model = model;
11650
11651         RSurf_ActiveModelEntity(ent, false, false, false);
11652
11653         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11654         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11655         VectorNormalize(localnormal);
11656         localsize = worldsize*rsurface.inversematrixscale;
11657         localmins[0] = localorigin[0] - localsize;
11658         localmins[1] = localorigin[1] - localsize;
11659         localmins[2] = localorigin[2] - localsize;
11660         localmaxs[0] = localorigin[0] + localsize;
11661         localmaxs[1] = localorigin[1] + localsize;
11662         localmaxs[2] = localorigin[2] + localsize;
11663
11664         //VectorCopy(localnormal, planes[4]);
11665         //VectorVectors(planes[4], planes[2], planes[0]);
11666         AnglesFromVectors(angles, localnormal, NULL, false);
11667         AngleVectors(angles, planes[0], planes[2], planes[4]);
11668         VectorNegate(planes[0], planes[1]);
11669         VectorNegate(planes[2], planes[3]);
11670         VectorNegate(planes[4], planes[5]);
11671         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11672         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11673         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11674         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11675         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11676         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11677
11678 #if 1
11679 // works
11680 {
11681         matrix4x4_t forwardprojection;
11682         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11683         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11684 }
11685 #else
11686 // broken
11687 {
11688         float projectionvector[4][3];
11689         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11690         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11691         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11692         projectionvector[0][0] = planes[0][0] * ilocalsize;
11693         projectionvector[0][1] = planes[1][0] * ilocalsize;
11694         projectionvector[0][2] = planes[2][0] * ilocalsize;
11695         projectionvector[1][0] = planes[0][1] * ilocalsize;
11696         projectionvector[1][1] = planes[1][1] * ilocalsize;
11697         projectionvector[1][2] = planes[2][1] * ilocalsize;
11698         projectionvector[2][0] = planes[0][2] * ilocalsize;
11699         projectionvector[2][1] = planes[1][2] * ilocalsize;
11700         projectionvector[2][2] = planes[2][2] * ilocalsize;
11701         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11702         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11703         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11704         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11705 }
11706 #endif
11707
11708         dynamic = model->surfmesh.isanimated;
11709         vertex3f = rsurface.modelvertex3f;
11710         numsurfacelist = model->nummodelsurfaces;
11711         surfacelist = model->sortedmodelsurfaces;
11712         surfaces = model->data_surfaces;
11713         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11714         {
11715                 surfaceindex = surfacelist[surfacelistindex];
11716                 surface = surfaces + surfaceindex;
11717                 // check cull box first because it rejects more than any other check
11718                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11719                         continue;
11720                 // skip transparent surfaces
11721                 texture = surface->texture;
11722                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11723                         continue;
11724                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11725                         continue;
11726                 numtriangles = surface->num_triangles;
11727                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11728                 {
11729                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11730                         {
11731                                 index = 3*e[cornerindex];
11732                                 VectorCopy(vertex3f + index, v[cornerindex]);
11733                         }
11734                         // cull backfaces
11735                         //TriangleNormal(v[0], v[1], v[2], normal);
11736                         //if (DotProduct(normal, localnormal) < 0.0f)
11737                         //      continue;
11738                         // clip by each of the box planes formed from the projection matrix
11739                         // if anything survives, we emit the decal
11740                         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]);
11741                         if (numpoints < 3)
11742                                 continue;
11743                         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]);
11744                         if (numpoints < 3)
11745                                 continue;
11746                         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]);
11747                         if (numpoints < 3)
11748                                 continue;
11749                         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]);
11750                         if (numpoints < 3)
11751                                 continue;
11752                         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]);
11753                         if (numpoints < 3)
11754                                 continue;
11755                         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]);
11756                         if (numpoints < 3)
11757                                 continue;
11758                         // some part of the triangle survived, so we have to accept it...
11759                         if (dynamic)
11760                         {
11761                                 // dynamic always uses the original triangle
11762                                 numpoints = 3;
11763                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11764                                 {
11765                                         index = 3*e[cornerindex];
11766                                         VectorCopy(vertex3f + index, v[cornerindex]);
11767                                 }
11768                         }
11769                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11770                         {
11771                                 // convert vertex positions to texcoords
11772                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11773                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11774                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11775                                 // calculate distance fade from the projection origin
11776                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11777                                 f = bound(0.0f, f, 1.0f);
11778                                 c[cornerindex][0] = r * f;
11779                                 c[cornerindex][1] = g * f;
11780                                 c[cornerindex][2] = b * f;
11781                                 c[cornerindex][3] = 1.0f;
11782                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11783                         }
11784                         if (dynamic)
11785                                 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);
11786                         else
11787                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11788                                         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);
11789                 }
11790         }
11791 }
11792
11793 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11794 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)
11795 {
11796         int renderentityindex;
11797         float worldmins[3];
11798         float worldmaxs[3];
11799         entity_render_t *ent;
11800
11801         if (!cl_decals_newsystem.integer)
11802                 return;
11803
11804         worldmins[0] = worldorigin[0] - worldsize;
11805         worldmins[1] = worldorigin[1] - worldsize;
11806         worldmins[2] = worldorigin[2] - worldsize;
11807         worldmaxs[0] = worldorigin[0] + worldsize;
11808         worldmaxs[1] = worldorigin[1] + worldsize;
11809         worldmaxs[2] = worldorigin[2] + worldsize;
11810
11811         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11812
11813         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11814         {
11815                 ent = r_refdef.scene.entities[renderentityindex];
11816                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11817                         continue;
11818
11819                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11820         }
11821 }
11822
11823 typedef struct r_decalsystem_splatqueue_s
11824 {
11825         vec3_t worldorigin;
11826         vec3_t worldnormal;
11827         float color[4];
11828         float tcrange[4];
11829         float worldsize;
11830         int decalsequence;
11831 }
11832 r_decalsystem_splatqueue_t;
11833
11834 int r_decalsystem_numqueued = 0;
11835 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11836
11837 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)
11838 {
11839         r_decalsystem_splatqueue_t *queue;
11840
11841         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11842                 return;
11843
11844         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11845         VectorCopy(worldorigin, queue->worldorigin);
11846         VectorCopy(worldnormal, queue->worldnormal);
11847         Vector4Set(queue->color, r, g, b, a);
11848         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11849         queue->worldsize = worldsize;
11850         queue->decalsequence = cl.decalsequence++;
11851 }
11852
11853 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11854 {
11855         int i;
11856         r_decalsystem_splatqueue_t *queue;
11857
11858         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11859                 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);
11860         r_decalsystem_numqueued = 0;
11861 }
11862
11863 extern cvar_t cl_decals_max;
11864 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11865 {
11866         int i;
11867         decalsystem_t *decalsystem = &ent->decalsystem;
11868         int numdecals;
11869         int killsequence;
11870         tridecal_t *decal;
11871         float frametime;
11872         float lifetime;
11873
11874         if (!decalsystem->numdecals)
11875                 return;
11876
11877         if (r_showsurfaces.integer)
11878                 return;
11879
11880         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11881         {
11882                 R_DecalSystem_Reset(decalsystem);
11883                 return;
11884         }
11885
11886         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11887         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11888
11889         if (decalsystem->lastupdatetime)
11890                 frametime = (cl.time - decalsystem->lastupdatetime);
11891         else
11892                 frametime = 0;
11893         decalsystem->lastupdatetime = cl.time;
11894         decal = decalsystem->decals;
11895         numdecals = decalsystem->numdecals;
11896
11897         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11898         {
11899                 if (decal->color4ub[0][3])
11900                 {
11901                         decal->lived += frametime;
11902                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11903                         {
11904                                 memset(decal, 0, sizeof(*decal));
11905                                 if (decalsystem->freedecal > i)
11906                                         decalsystem->freedecal = i;
11907                         }
11908                 }
11909         }
11910         decal = decalsystem->decals;
11911         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11912                 numdecals--;
11913
11914         // collapse the array by shuffling the tail decals into the gaps
11915         for (;;)
11916         {
11917                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11918                         decalsystem->freedecal++;
11919                 if (decalsystem->freedecal == numdecals)
11920                         break;
11921                 decal[decalsystem->freedecal] = decal[--numdecals];
11922         }
11923
11924         decalsystem->numdecals = numdecals;
11925
11926         if (numdecals <= 0)
11927         {
11928                 // if there are no decals left, reset decalsystem
11929                 R_DecalSystem_Reset(decalsystem);
11930         }
11931 }
11932
11933 extern skinframe_t *decalskinframe;
11934 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11935 {
11936         int i;
11937         decalsystem_t *decalsystem = &ent->decalsystem;
11938         int numdecals;
11939         tridecal_t *decal;
11940         float faderate;
11941         float alpha;
11942         float *v3f;
11943         float *c4f;
11944         float *t2f;
11945         const int *e;
11946         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11947         int numtris = 0;
11948
11949         numdecals = decalsystem->numdecals;
11950         if (!numdecals)
11951                 return;
11952
11953         if (r_showsurfaces.integer)
11954                 return;
11955
11956         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11957         {
11958                 R_DecalSystem_Reset(decalsystem);
11959                 return;
11960         }
11961
11962         // if the model is static it doesn't matter what value we give for
11963         // wantnormals and wanttangents, so this logic uses only rules applicable
11964         // to a model, knowing that they are meaningless otherwise
11965         if (ent == r_refdef.scene.worldentity)
11966                 RSurf_ActiveWorldEntity();
11967         else
11968                 RSurf_ActiveModelEntity(ent, false, false, false);
11969
11970         decalsystem->lastupdatetime = cl.time;
11971         decal = decalsystem->decals;
11972
11973         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11974
11975         // update vertex positions for animated models
11976         v3f = decalsystem->vertex3f;
11977         c4f = decalsystem->color4f;
11978         t2f = decalsystem->texcoord2f;
11979         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11980         {
11981                 if (!decal->color4ub[0][3])
11982                         continue;
11983
11984                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11985                         continue;
11986
11987                 // update color values for fading decals
11988                 if (decal->lived >= cl_decals_time.value)
11989                 {
11990                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11991                         alpha *= (1.0f/255.0f);
11992                 }
11993                 else
11994                         alpha = 1.0f/255.0f;
11995
11996                 c4f[ 0] = decal->color4ub[0][0] * alpha;
11997                 c4f[ 1] = decal->color4ub[0][1] * alpha;
11998                 c4f[ 2] = decal->color4ub[0][2] * alpha;
11999                 c4f[ 3] = 1;
12000                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12001                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12002                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12003                 c4f[ 7] = 1;
12004                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12005                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12006                 c4f[10] = decal->color4ub[2][2] * alpha;
12007                 c4f[11] = 1;
12008
12009                 t2f[0] = decal->texcoord2f[0][0];
12010                 t2f[1] = decal->texcoord2f[0][1];
12011                 t2f[2] = decal->texcoord2f[1][0];
12012                 t2f[3] = decal->texcoord2f[1][1];
12013                 t2f[4] = decal->texcoord2f[2][0];
12014                 t2f[5] = decal->texcoord2f[2][1];
12015
12016                 // update vertex positions for animated models
12017                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12018                 {
12019                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12020                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12021                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12022                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12023                 }
12024                 else
12025                 {
12026                         VectorCopy(decal->vertex3f[0], v3f);
12027                         VectorCopy(decal->vertex3f[1], v3f + 3);
12028                         VectorCopy(decal->vertex3f[2], v3f + 6);
12029                 }
12030
12031                 v3f += 9;
12032                 c4f += 12;
12033                 t2f += 6;
12034                 numtris++;
12035         }
12036
12037         if (numtris > 0)
12038         {
12039                 r_refdef.stats.drawndecals += numtris;
12040
12041                 if (r_refdef.fogenabled)
12042                 {
12043                         switch(vid.renderpath)
12044                         {
12045                         case RENDERPATH_GL20:
12046                         case RENDERPATH_CGGL:
12047                         case RENDERPATH_GL13:
12048                         case RENDERPATH_GL11:
12049                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
12050                                 {
12051                                         alpha = RSurf_FogVertex(v3f);
12052                                         c4f[0] *= alpha;
12053                                         c4f[1] *= alpha;
12054                                         c4f[2] *= alpha;
12055                                 }
12056                                 break;
12057                         }
12058                 }
12059
12060                 // now render the decals all at once
12061                 // (this assumes they all use one particle font texture!)
12062                 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);
12063                 R_Mesh_ResetTextureState();
12064                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12065                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12066                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12067                 GL_DepthMask(false);
12068                 GL_DepthRange(0, 1);
12069                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12070                 GL_DepthTest(true);
12071                 GL_CullFace(GL_NONE);
12072                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12073                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12074                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12075         }
12076 }
12077
12078 static void R_DrawModelDecals(void)
12079 {
12080         int i, numdecals;
12081
12082         // fade faster when there are too many decals
12083         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12084         for (i = 0;i < r_refdef.scene.numentities;i++)
12085                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12086
12087         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12088         for (i = 0;i < r_refdef.scene.numentities;i++)
12089                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12090                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12091
12092         R_DecalSystem_ApplySplatEntitiesQueue();
12093
12094         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12095         for (i = 0;i < r_refdef.scene.numentities;i++)
12096                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12097
12098         r_refdef.stats.totaldecals += numdecals;
12099
12100         if (r_showsurfaces.integer)
12101                 return;
12102
12103         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12104
12105         for (i = 0;i < r_refdef.scene.numentities;i++)
12106         {
12107                 if (!r_refdef.viewcache.entityvisible[i])
12108                         continue;
12109                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12110                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12111         }
12112 }
12113
12114 void R_DrawDebugModel(void)
12115 {
12116         entity_render_t *ent = rsurface.entity;
12117         int i, j, k, l, flagsmask;
12118         q3mbrush_t *brush;
12119         const msurface_t *surface;
12120         dp_model_t *model = ent->model;
12121         vec3_t v;
12122
12123         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12124
12125         R_Mesh_ColorPointer(NULL, 0, 0);
12126         R_Mesh_ResetTextureState();
12127         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12128         GL_DepthRange(0, 1);
12129         GL_DepthTest(!r_showdisabledepthtest.integer);
12130         GL_DepthMask(false);
12131         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12132
12133         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12134         {
12135                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12136                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12137                 {
12138                         if (brush->colbrushf && brush->colbrushf->numtriangles)
12139                         {
12140                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12141                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12142                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12143                         }
12144                 }
12145                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12146                 {
12147                         if (surface->num_collisiontriangles)
12148                         {
12149                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12150                                 GL_Color((i & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((i >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12151                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12152                         }
12153                 }
12154         }
12155
12156         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12157
12158         if (r_showtris.integer || r_shownormals.integer)
12159         {
12160                 if (r_showdisabledepthtest.integer)
12161                 {
12162                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12163                         GL_DepthMask(false);
12164                 }
12165                 else
12166                 {
12167                         GL_BlendFunc(GL_ONE, GL_ZERO);
12168                         GL_DepthMask(true);
12169                 }
12170                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12171                 {
12172                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12173                                 continue;
12174                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12175                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12176                         {
12177                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12178                                 if (r_showtris.value > 0)
12179                                 {
12180                                         if (!rsurface.texture->currentlayers->depthmask)
12181                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12182                                         else if (ent == r_refdef.scene.worldentity)
12183                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12184                                         else
12185                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12186                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12187                                         R_Mesh_ColorPointer(NULL, 0, 0);
12188                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12189                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12190                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12191                                         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);
12192                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12193                                         CHECKGLERROR
12194                                 }
12195                                 if (r_shownormals.value < 0)
12196                                 {
12197                                         qglBegin(GL_LINES);
12198                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12199                                         {
12200                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12201                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12202                                                 qglVertex3f(v[0], v[1], v[2]);
12203                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12204                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12205                                                 qglVertex3f(v[0], v[1], v[2]);
12206                                         }
12207                                         qglEnd();
12208                                         CHECKGLERROR
12209                                 }
12210                                 if (r_shownormals.value > 0)
12211                                 {
12212                                         qglBegin(GL_LINES);
12213                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12214                                         {
12215                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12216                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12217                                                 qglVertex3f(v[0], v[1], v[2]);
12218                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12219                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12220                                                 qglVertex3f(v[0], v[1], v[2]);
12221                                         }
12222                                         qglEnd();
12223                                         CHECKGLERROR
12224                                         qglBegin(GL_LINES);
12225                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12226                                         {
12227                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12228                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12229                                                 qglVertex3f(v[0], v[1], v[2]);
12230                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12231                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12232                                                 qglVertex3f(v[0], v[1], v[2]);
12233                                         }
12234                                         qglEnd();
12235                                         CHECKGLERROR
12236                                         qglBegin(GL_LINES);
12237                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12238                                         {
12239                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12240                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12241                                                 qglVertex3f(v[0], v[1], v[2]);
12242                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12243                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12244                                                 qglVertex3f(v[0], v[1], v[2]);
12245                                         }
12246                                         qglEnd();
12247                                         CHECKGLERROR
12248                                 }
12249                         }
12250                 }
12251                 rsurface.texture = NULL;
12252         }
12253 }
12254
12255 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12256 int r_maxsurfacelist = 0;
12257 const msurface_t **r_surfacelist = NULL;
12258 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12259 {
12260         int i, j, endj, flagsmask;
12261         dp_model_t *model = r_refdef.scene.worldmodel;
12262         msurface_t *surfaces;
12263         unsigned char *update;
12264         int numsurfacelist = 0;
12265         if (model == NULL)
12266                 return;
12267
12268         if (r_maxsurfacelist < model->num_surfaces)
12269         {
12270                 r_maxsurfacelist = model->num_surfaces;
12271                 if (r_surfacelist)
12272                         Mem_Free((msurface_t**)r_surfacelist);
12273                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12274         }
12275
12276         RSurf_ActiveWorldEntity();
12277
12278         surfaces = model->data_surfaces;
12279         update = model->brushq1.lightmapupdateflags;
12280
12281         // update light styles on this submodel
12282         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12283         {
12284                 model_brush_lightstyleinfo_t *style;
12285                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12286                 {
12287                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12288                         {
12289                                 int *list = style->surfacelist;
12290                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12291                                 for (j = 0;j < style->numsurfaces;j++)
12292                                         update[list[j]] = true;
12293                         }
12294                 }
12295         }
12296
12297         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12298
12299         if (debug)
12300         {
12301                 R_DrawDebugModel();
12302                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12303                 return;
12304         }
12305
12306         rsurface.uselightmaptexture = false;
12307         rsurface.texture = NULL;
12308         rsurface.rtlight = NULL;
12309         numsurfacelist = 0;
12310         // add visible surfaces to draw list
12311         for (i = 0;i < model->nummodelsurfaces;i++)
12312         {
12313                 j = model->sortedmodelsurfaces[i];
12314                 if (r_refdef.viewcache.world_surfacevisible[j])
12315                         r_surfacelist[numsurfacelist++] = surfaces + j;
12316         }
12317         // update lightmaps if needed
12318         if (model->brushq1.firstrender)
12319         {
12320                 model->brushq1.firstrender = false;
12321                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12322                         if (update[j])
12323                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12324         }
12325         else if (update)
12326         {
12327                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12328                         if (r_refdef.viewcache.world_surfacevisible[j])
12329                                 if (update[j])
12330                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12331         }
12332         // don't do anything if there were no surfaces
12333         if (!numsurfacelist)
12334         {
12335                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12336                 return;
12337         }
12338         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12339         GL_AlphaTest(false);
12340
12341         // add to stats if desired
12342         if (r_speeds.integer && !skysurfaces && !depthonly)
12343         {
12344                 r_refdef.stats.world_surfaces += numsurfacelist;
12345                 for (j = 0;j < numsurfacelist;j++)
12346                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12347         }
12348
12349         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12350 }
12351
12352 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12353 {
12354         int i, j, endj, flagsmask;
12355         dp_model_t *model = ent->model;
12356         msurface_t *surfaces;
12357         unsigned char *update;
12358         int numsurfacelist = 0;
12359         if (model == NULL)
12360                 return;
12361
12362         if (r_maxsurfacelist < model->num_surfaces)
12363         {
12364                 r_maxsurfacelist = model->num_surfaces;
12365                 if (r_surfacelist)
12366                         Mem_Free((msurface_t **)r_surfacelist);
12367                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12368         }
12369
12370         // if the model is static it doesn't matter what value we give for
12371         // wantnormals and wanttangents, so this logic uses only rules applicable
12372         // to a model, knowing that they are meaningless otherwise
12373         if (ent == r_refdef.scene.worldentity)
12374                 RSurf_ActiveWorldEntity();
12375         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12376                 RSurf_ActiveModelEntity(ent, false, false, false);
12377         else if (prepass)
12378                 RSurf_ActiveModelEntity(ent, true, true, true);
12379         else if (depthonly)
12380         {
12381                 switch (vid.renderpath)
12382                 {
12383                 case RENDERPATH_GL20:
12384                 case RENDERPATH_CGGL:
12385                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12386                         break;
12387                 case RENDERPATH_GL13:
12388                 case RENDERPATH_GL11:
12389                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12390                         break;
12391                 }
12392         }
12393         else
12394         {
12395                 switch (vid.renderpath)
12396                 {
12397                 case RENDERPATH_GL20:
12398                 case RENDERPATH_CGGL:
12399                         RSurf_ActiveModelEntity(ent, true, true, false);
12400                         break;
12401                 case RENDERPATH_GL13:
12402                 case RENDERPATH_GL11:
12403                         RSurf_ActiveModelEntity(ent, true, false, false);
12404                         break;
12405                 }
12406         }
12407
12408         surfaces = model->data_surfaces;
12409         update = model->brushq1.lightmapupdateflags;
12410
12411         // update light styles
12412         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12413         {
12414                 model_brush_lightstyleinfo_t *style;
12415                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12416                 {
12417                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12418                         {
12419                                 int *list = style->surfacelist;
12420                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12421                                 for (j = 0;j < style->numsurfaces;j++)
12422                                         update[list[j]] = true;
12423                         }
12424                 }
12425         }
12426
12427         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12428
12429         if (debug)
12430         {
12431                 R_DrawDebugModel();
12432                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12433                 return;
12434         }
12435
12436         rsurface.uselightmaptexture = false;
12437         rsurface.texture = NULL;
12438         rsurface.rtlight = NULL;
12439         numsurfacelist = 0;
12440         // add visible surfaces to draw list
12441         for (i = 0;i < model->nummodelsurfaces;i++)
12442                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12443         // don't do anything if there were no surfaces
12444         if (!numsurfacelist)
12445         {
12446                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12447                 return;
12448         }
12449         // update lightmaps if needed
12450         if (update)
12451         {
12452                 int updated = 0;
12453                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12454                 {
12455                         if (update[j])
12456                         {
12457                                 updated++;
12458                                 R_BuildLightMap(ent, surfaces + j);
12459                         }
12460                 }
12461         }
12462         if (update)
12463                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12464                         if (update[j])
12465                                 R_BuildLightMap(ent, surfaces + j);
12466         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12467         GL_AlphaTest(false);
12468
12469         // add to stats if desired
12470         if (r_speeds.integer && !skysurfaces && !depthonly)
12471         {
12472                 r_refdef.stats.entities_surfaces += numsurfacelist;
12473                 for (j = 0;j < numsurfacelist;j++)
12474                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12475         }
12476
12477         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12478 }
12479
12480 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12481 {
12482         static texture_t texture;
12483         static msurface_t surface;
12484         const msurface_t *surfacelist = &surface;
12485
12486         // fake enough texture and surface state to render this geometry
12487
12488         texture.update_lastrenderframe = -1; // regenerate this texture
12489         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12490         texture.currentskinframe = skinframe;
12491         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12492         texture.specularscalemod = 1;
12493         texture.specularpowermod = 1;
12494
12495         surface.texture = &texture;
12496         surface.num_triangles = numtriangles;
12497         surface.num_firsttriangle = firsttriangle;
12498         surface.num_vertices = numvertices;
12499         surface.num_firstvertex = firstvertex;
12500
12501         // now render it
12502         rsurface.texture = R_GetCurrentTexture(surface.texture);
12503         rsurface.uselightmaptexture = false;
12504         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12505 }
12506
12507 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)
12508 {
12509         static msurface_t surface;
12510         const msurface_t *surfacelist = &surface;
12511
12512         // fake enough texture and surface state to render this geometry
12513
12514         surface.texture = texture;
12515         surface.num_triangles = numtriangles;
12516         surface.num_firsttriangle = firsttriangle;
12517         surface.num_vertices = numvertices;
12518         surface.num_firstvertex = firstvertex;
12519
12520         // now render it
12521         rsurface.texture = R_GetCurrentTexture(surface.texture);
12522         rsurface.uselightmaptexture = false;
12523         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12524 }