]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
when r_shadow_shadowmapping is enabled, r_shadows uses shadowmaps instead of stencils
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28
29 mempool_t *r_main_mempool;
30 rtexturepool_t *r_main_texturepool;
31
32 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
33
34 static qboolean r_loadnormalmap;
35 static qboolean r_loadgloss;
36 qboolean r_loadfog;
37 static qboolean r_loaddds;
38 static qboolean r_savedds;
39
40 //
41 // screen size info
42 //
43 r_refdef_t r_refdef;
44
45 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
46 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
47 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
48 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
49 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
50 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
51 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
52 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
53
54 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
55 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
56 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
57 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
58 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
59
60 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
61 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
62 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
63 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
64 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
65 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
66 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
67 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
68 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
69 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
70 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
71 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
72 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
73 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
74 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
75 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
76 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
77 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
78 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
79 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
80 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
81 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
82 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
83 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
84 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
85 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
86 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
87 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
88 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
89 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
90 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
91 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
92 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
93 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
94 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
95 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
96 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
97 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
98 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
99 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
100 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
101 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
102
103 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
104 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
105 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
106 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
107 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
108 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
109 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
110 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
111
112 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
113 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
114
115 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
116 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
117 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
118 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
119 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
120
121 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
122 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
123 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
124
125 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)"};
126 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
127 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
128 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
129 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
130 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)"};
131 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)"};
132 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)"};
133 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)"};
134
135 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)"};
136 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
137 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"};
138 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
139 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
140
141 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
142 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
143 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
144 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
145
146 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
147 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
148 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
149 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
150 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
151 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
152 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
153
154 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
155 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
156 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
157 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)"};
158
159 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"};
160
161 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"};
162
163 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
164
165 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
166 cvar_t r_batchmode = {0, "r_batchmode", "1", "selects method of rendering multiple surfaces with one driver call (values are 0, 1, 2, etc...)"};
167 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"};
168 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
169 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
170 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
171 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
172 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)"};
173
174 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
175
176 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)"};
177
178 extern cvar_t v_glslgamma;
179
180 extern qboolean v_flipped_state;
181
182 static struct r_bloomstate_s
183 {
184         qboolean enabled;
185         qboolean hdr;
186
187         int bloomwidth, bloomheight;
188
189         int screentexturewidth, screentextureheight;
190         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
191
192         int bloomtexturewidth, bloomtextureheight;
193         rtexture_t *texture_bloom;
194
195         // arrays for rendering the screen passes
196         float screentexcoord2f[8];
197         float bloomtexcoord2f[8];
198         float offsettexcoord2f[8];
199
200         r_viewport_t viewport;
201 }
202 r_bloomstate;
203
204 r_waterstate_t r_waterstate;
205
206 /// shadow volume bsp struct with automatically growing nodes buffer
207 svbsp_t r_svbsp;
208
209 rtexture_t *r_texture_blanknormalmap;
210 rtexture_t *r_texture_white;
211 rtexture_t *r_texture_grey128;
212 rtexture_t *r_texture_black;
213 rtexture_t *r_texture_notexture;
214 rtexture_t *r_texture_whitecube;
215 rtexture_t *r_texture_normalizationcube;
216 rtexture_t *r_texture_fogattenuation;
217 rtexture_t *r_texture_gammaramps;
218 unsigned int r_texture_gammaramps_serial;
219 //rtexture_t *r_texture_fogintensity;
220 rtexture_t *r_texture_reflectcube;
221
222 // TODO: hash lookups?
223 typedef struct cubemapinfo_s
224 {
225         char basename[64];
226         rtexture_t *texture;
227 }
228 cubemapinfo_t;
229
230 int r_texture_numcubemaps;
231 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
232
233 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
234 unsigned int r_numqueries;
235 unsigned int r_maxqueries;
236
237 typedef struct r_qwskincache_s
238 {
239         char name[MAX_QPATH];
240         skinframe_t *skinframe;
241 }
242 r_qwskincache_t;
243
244 static r_qwskincache_t *r_qwskincache;
245 static int r_qwskincache_size;
246
247 /// vertex coordinates for a quad that covers the screen exactly
248 const float r_screenvertex3f[12] =
249 {
250         0, 0, 0,
251         1, 0, 0,
252         1, 1, 0,
253         0, 1, 0
254 };
255
256 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
257 {
258         int i;
259         for (i = 0;i < verts;i++)
260         {
261                 out[0] = in[0] * r;
262                 out[1] = in[1] * g;
263                 out[2] = in[2] * b;
264                 out[3] = in[3];
265                 in += 4;
266                 out += 4;
267         }
268 }
269
270 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
271 {
272         int i;
273         for (i = 0;i < verts;i++)
274         {
275                 out[0] = r;
276                 out[1] = g;
277                 out[2] = b;
278                 out[3] = a;
279                 out += 4;
280         }
281 }
282
283 // FIXME: move this to client?
284 void FOG_clear(void)
285 {
286         if (gamemode == GAME_NEHAHRA)
287         {
288                 Cvar_Set("gl_fogenable", "0");
289                 Cvar_Set("gl_fogdensity", "0.2");
290                 Cvar_Set("gl_fogred", "0.3");
291                 Cvar_Set("gl_foggreen", "0.3");
292                 Cvar_Set("gl_fogblue", "0.3");
293         }
294         r_refdef.fog_density = 0;
295         r_refdef.fog_red = 0;
296         r_refdef.fog_green = 0;
297         r_refdef.fog_blue = 0;
298         r_refdef.fog_alpha = 1;
299         r_refdef.fog_start = 0;
300         r_refdef.fog_end = 16384;
301         r_refdef.fog_height = 1<<30;
302         r_refdef.fog_fadedepth = 128;
303 }
304
305 static void R_BuildBlankTextures(void)
306 {
307         unsigned char data[4];
308         data[2] = 128; // normal X
309         data[1] = 128; // normal Y
310         data[0] = 255; // normal Z
311         data[3] = 128; // height
312         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
313         data[0] = 255;
314         data[1] = 255;
315         data[2] = 255;
316         data[3] = 255;
317         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
318         data[0] = 128;
319         data[1] = 128;
320         data[2] = 128;
321         data[3] = 255;
322         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
323         data[0] = 0;
324         data[1] = 0;
325         data[2] = 0;
326         data[3] = 255;
327         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
328 }
329
330 static void R_BuildNoTexture(void)
331 {
332         int x, y;
333         unsigned char pix[16][16][4];
334         // this makes a light grey/dark grey checkerboard texture
335         for (y = 0;y < 16;y++)
336         {
337                 for (x = 0;x < 16;x++)
338                 {
339                         if ((y < 8) ^ (x < 8))
340                         {
341                                 pix[y][x][0] = 128;
342                                 pix[y][x][1] = 128;
343                                 pix[y][x][2] = 128;
344                                 pix[y][x][3] = 255;
345                         }
346                         else
347                         {
348                                 pix[y][x][0] = 64;
349                                 pix[y][x][1] = 64;
350                                 pix[y][x][2] = 64;
351                                 pix[y][x][3] = 255;
352                         }
353                 }
354         }
355         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
356 }
357
358 static void R_BuildWhiteCube(void)
359 {
360         unsigned char data[6*1*1*4];
361         memset(data, 255, sizeof(data));
362         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
363 }
364
365 static void R_BuildNormalizationCube(void)
366 {
367         int x, y, side;
368         vec3_t v;
369         vec_t s, t, intensity;
370 #define NORMSIZE 64
371         unsigned char *data;
372         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
373         for (side = 0;side < 6;side++)
374         {
375                 for (y = 0;y < NORMSIZE;y++)
376                 {
377                         for (x = 0;x < NORMSIZE;x++)
378                         {
379                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
380                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
381                                 switch(side)
382                                 {
383                                 default:
384                                 case 0:
385                                         v[0] = 1;
386                                         v[1] = -t;
387                                         v[2] = -s;
388                                         break;
389                                 case 1:
390                                         v[0] = -1;
391                                         v[1] = -t;
392                                         v[2] = s;
393                                         break;
394                                 case 2:
395                                         v[0] = s;
396                                         v[1] = 1;
397                                         v[2] = t;
398                                         break;
399                                 case 3:
400                                         v[0] = s;
401                                         v[1] = -1;
402                                         v[2] = -t;
403                                         break;
404                                 case 4:
405                                         v[0] = s;
406                                         v[1] = -t;
407                                         v[2] = 1;
408                                         break;
409                                 case 5:
410                                         v[0] = -s;
411                                         v[1] = -t;
412                                         v[2] = -1;
413                                         break;
414                                 }
415                                 intensity = 127.0f / sqrt(DotProduct(v, v));
416                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
417                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
418                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
419                                 data[((side*64+y)*64+x)*4+3] = 255;
420                         }
421                 }
422         }
423         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
424         Mem_Free(data);
425 }
426
427 static void R_BuildFogTexture(void)
428 {
429         int x, b;
430 #define FOGWIDTH 256
431         unsigned char data1[FOGWIDTH][4];
432         //unsigned char data2[FOGWIDTH][4];
433         double d, r, alpha;
434
435         r_refdef.fogmasktable_start = r_refdef.fog_start;
436         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
437         r_refdef.fogmasktable_range = r_refdef.fogrange;
438         r_refdef.fogmasktable_density = r_refdef.fog_density;
439
440         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
441         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
442         {
443                 d = (x * r - r_refdef.fogmasktable_start);
444                 if(developer_extra.integer)
445                         Con_DPrintf("%f ", d);
446                 d = max(0, d);
447                 if (r_fog_exp2.integer)
448                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
449                 else
450                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
451                 if(developer_extra.integer)
452                         Con_DPrintf(" : %f ", alpha);
453                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
454                 if(developer_extra.integer)
455                         Con_DPrintf(" = %f\n", alpha);
456                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
457         }
458
459         for (x = 0;x < FOGWIDTH;x++)
460         {
461                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
462                 data1[x][0] = b;
463                 data1[x][1] = b;
464                 data1[x][2] = b;
465                 data1[x][3] = 255;
466                 //data2[x][0] = 255 - b;
467                 //data2[x][1] = 255 - b;
468                 //data2[x][2] = 255 - b;
469                 //data2[x][3] = 255;
470         }
471         if (r_texture_fogattenuation)
472         {
473                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
474                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
475         }
476         else
477         {
478                 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);
479                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
480         }
481 }
482
483 //=======================================================================================================================================================
484
485 static const char *builtinshaderstring =
486 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
487 "// written by Forest 'LordHavoc' Hale\n"
488 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
489 "\n"
490 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
491 "# define USEFOG\n"
492 "#endif\n"
493 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
494 "#define USELIGHTMAP\n"
495 "#endif\n"
496 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
497 "#define USEEYEVECTOR\n"
498 "#endif\n"
499 "\n"
500 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
501 "# extension GL_ARB_texture_rectangle : enable\n"
502 "#endif\n"
503 "\n"
504 "#ifdef USESHADOWMAP2D\n"
505 "# ifdef GL_EXT_gpu_shader4\n"
506 "#   extension GL_EXT_gpu_shader4 : enable\n"
507 "# endif\n"
508 "# ifdef GL_ARB_texture_gather\n"
509 "#   extension GL_ARB_texture_gather : enable\n"
510 "# else\n"
511 "#   ifdef GL_AMD_texture_texture4\n"
512 "#     extension GL_AMD_texture_texture4 : enable\n"
513 "#   endif\n"
514 "# endif\n"
515 "#endif\n"
516 "\n"
517 "#ifdef USESHADOWMAPCUBE\n"
518 "# extension GL_EXT_gpu_shader4 : enable\n"
519 "#endif\n"
520 "\n"
521 "//#ifdef USESHADOWSAMPLER\n"
522 "//# extension GL_ARB_shadow : enable\n"
523 "//#endif\n"
524 "\n"
525 "//#ifdef __GLSL_CG_DATA_TYPES\n"
526 "//# define myhalf half\n"
527 "//# define myhalf2 half2\n"
528 "//# define myhalf3 half3\n"
529 "//# define myhalf4 half4\n"
530 "//#else\n"
531 "# define myhalf float\n"
532 "# define myhalf2 vec2\n"
533 "# define myhalf3 vec3\n"
534 "# define myhalf4 vec4\n"
535 "//#endif\n"
536 "\n"
537 "#ifdef VERTEX_SHADER\n"
538 "uniform mat4 ModelViewProjectionMatrix;\n"
539 "#endif\n"
540 "\n"
541 "#ifdef MODE_DEPTH_OR_SHADOW\n"
542 "#ifdef VERTEX_SHADER\n"
543 "void main(void)\n"
544 "{\n"
545 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
546 "}\n"
547 "#endif\n"
548 "#else // !MODE_DEPTH_ORSHADOW\n"
549 "\n"
550 "\n"
551 "\n"
552 "\n"
553 "#ifdef MODE_SHOWDEPTH\n"
554 "#ifdef VERTEX_SHADER\n"
555 "void main(void)\n"
556 "{\n"
557 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
558 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
559 "}\n"
560 "#endif\n"
561 "\n"
562 "#ifdef FRAGMENT_SHADER\n"
563 "void main(void)\n"
564 "{\n"
565 "       gl_FragColor = gl_Color;\n"
566 "}\n"
567 "#endif\n"
568 "#else // !MODE_SHOWDEPTH\n"
569 "\n"
570 "\n"
571 "\n"
572 "\n"
573 "#ifdef MODE_POSTPROCESS\n"
574 "varying vec2 TexCoord1;\n"
575 "varying vec2 TexCoord2;\n"
576 "\n"
577 "#ifdef VERTEX_SHADER\n"
578 "void main(void)\n"
579 "{\n"
580 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
581 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
582 "#ifdef USEBLOOM\n"
583 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
584 "#endif\n"
585 "}\n"
586 "#endif\n"
587 "\n"
588 "#ifdef FRAGMENT_SHADER\n"
589 "uniform sampler2D Texture_First;\n"
590 "#ifdef USEBLOOM\n"
591 "uniform sampler2D Texture_Second;\n"
592 "#endif\n"
593 "#ifdef USEGAMMARAMPS\n"
594 "uniform sampler2D Texture_GammaRamps;\n"
595 "#endif\n"
596 "#ifdef USESATURATION\n"
597 "uniform float Saturation;\n"
598 "#endif\n"
599 "#ifdef USEVIEWTINT\n"
600 "uniform vec4 ViewTintColor;\n"
601 "#endif\n"
602 "//uncomment these if you want to use them:\n"
603 "uniform vec4 UserVec1;\n"
604 "// uniform vec4 UserVec2;\n"
605 "// uniform vec4 UserVec3;\n"
606 "// uniform vec4 UserVec4;\n"
607 "// uniform float ClientTime;\n"
608 "uniform vec2 PixelSize;\n"
609 "void main(void)\n"
610 "{\n"
611 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
612 "#ifdef USEBLOOM\n"
613 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
614 "#endif\n"
615 "#ifdef USEVIEWTINT\n"
616 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
617 "#endif\n"
618 "\n"
619 "#ifdef USEPOSTPROCESSING\n"
620 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
621 "// 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"
622 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
623 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
624 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
625 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
626 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
627 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
628 "#endif\n"
629 "\n"
630 "#ifdef USESATURATION\n"
631 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
632 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
633 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
634 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
635 "#endif\n"
636 "\n"
637 "#ifdef USEGAMMARAMPS\n"
638 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
639 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
640 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
641 "#endif\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_POSTPROCESS\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_GENERIC\n"
650 "#ifdef USEDIFFUSE\n"
651 "varying vec2 TexCoord1;\n"
652 "#endif\n"
653 "#ifdef USESPECULAR\n"
654 "varying vec2 TexCoord2;\n"
655 "#endif\n"
656 "#ifdef VERTEX_SHADER\n"
657 "void main(void)\n"
658 "{\n"
659 "       gl_FrontColor = gl_Color;\n"
660 "#ifdef USEDIFFUSE\n"
661 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
662 "#endif\n"
663 "#ifdef USESPECULAR\n"
664 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
665 "#endif\n"
666 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
667 "}\n"
668 "#endif\n"
669 "\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "#ifdef USEDIFFUSE\n"
672 "uniform sampler2D Texture_First;\n"
673 "#endif\n"
674 "#ifdef USESPECULAR\n"
675 "uniform sampler2D Texture_Second;\n"
676 "#endif\n"
677 "\n"
678 "void main(void)\n"
679 "{\n"
680 "       gl_FragColor = gl_Color;\n"
681 "#ifdef USEDIFFUSE\n"
682 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
683 "#endif\n"
684 "\n"
685 "#ifdef USESPECULAR\n"
686 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
687 "# ifdef USECOLORMAPPING\n"
688 "       gl_FragColor *= tex2;\n"
689 "# endif\n"
690 "# ifdef USEGLOW\n"
691 "       gl_FragColor += tex2;\n"
692 "# endif\n"
693 "# ifdef USEVERTEXTEXTUREBLEND\n"
694 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
695 "# endif\n"
696 "#endif\n"
697 "}\n"
698 "#endif\n"
699 "#else // !MODE_GENERIC\n"
700 "\n"
701 "\n"
702 "\n"
703 "\n"
704 "#ifdef MODE_BLOOMBLUR\n"
705 "varying TexCoord;\n"
706 "#ifdef VERTEX_SHADER\n"
707 "void main(void)\n"
708 "{\n"
709 "       gl_FrontColor = gl_Color;\n"
710 "       TexCoord = gl_MultiTexCoord0.xy;\n"
711 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
712 "}\n"
713 "#endif\n"
714 "\n"
715 "#ifdef FRAGMENT_SHADER\n"
716 "uniform sampler2D Texture_First;\n"
717 "uniform vec4 BloomBlur_Parameters;\n"
718 "\n"
719 "void main(void)\n"
720 "{\n"
721 "       int i;\n"
722 "       vec2 tc = TexCoord;\n"
723 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
724 "       tc += BloomBlur_Parameters.xy;\n"
725 "       for (i = 1;i < SAMPLES;i++)\n"
726 "       {\n"
727 "               color += texture2D(Texture_First, tc).rgb;\n"
728 "               tc += BloomBlur_Parameters.xy;\n"
729 "       }\n"
730 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
731 "}\n"
732 "#endif\n"
733 "#else // !MODE_BLOOMBLUR\n"
734 "#ifdef MODE_REFRACTION\n"
735 "varying vec2 TexCoord;\n"
736 "varying vec4 ModelViewProjectionPosition;\n"
737 "uniform mat4 TexMatrix;\n"
738 "#ifdef VERTEX_SHADER\n"
739 "\n"
740 "void main(void)\n"
741 "{\n"
742 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
743 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
744 "       ModelViewProjectionPosition = gl_Position;\n"
745 "}\n"
746 "#endif\n"
747 "\n"
748 "#ifdef FRAGMENT_SHADER\n"
749 "uniform sampler2D Texture_Normal;\n"
750 "uniform sampler2D Texture_Refraction;\n"
751 "uniform sampler2D Texture_Reflection;\n"
752 "\n"
753 "uniform vec4 DistortScaleRefractReflect;\n"
754 "uniform vec4 ScreenScaleRefractReflect;\n"
755 "uniform vec4 ScreenCenterRefractReflect;\n"
756 "uniform vec4 RefractColor;\n"
757 "uniform vec4 ReflectColor;\n"
758 "uniform float ReflectFactor;\n"
759 "uniform float ReflectOffset;\n"
760 "\n"
761 "void main(void)\n"
762 "{\n"
763 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
764 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
765 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
766 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
767 "       // FIXME temporary hack to detect the case that the reflection\n"
768 "       // gets blackened at edges due to leaving the area that contains actual\n"
769 "       // content.\n"
770 "       // Remove this 'ack once we have a better way to stop this thing from\n"
771 "       // 'appening.\n"
772 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
773 "       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 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
777 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
778 "}\n"
779 "#endif\n"
780 "#else // !MODE_REFRACTION\n"
781 "\n"
782 "\n"
783 "\n"
784 "\n"
785 "#ifdef MODE_WATER\n"
786 "varying vec2 TexCoord;\n"
787 "varying vec3 EyeVector;\n"
788 "varying vec4 ModelViewProjectionPosition;\n"
789 "#ifdef VERTEX_SHADER\n"
790 "uniform vec3 EyePosition;\n"
791 "uniform mat4 TexMatrix;\n"
792 "\n"
793 "void main(void)\n"
794 "{\n"
795 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
796 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
797 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
798 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
799 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
800 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
801 "       ModelViewProjectionPosition = gl_Position;\n"
802 "}\n"
803 "#endif\n"
804 "\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "uniform sampler2D Texture_Normal;\n"
807 "uniform sampler2D Texture_Refraction;\n"
808 "uniform sampler2D Texture_Reflection;\n"
809 "\n"
810 "uniform vec4 DistortScaleRefractReflect;\n"
811 "uniform vec4 ScreenScaleRefractReflect;\n"
812 "uniform vec4 ScreenCenterRefractReflect;\n"
813 "uniform vec4 RefractColor;\n"
814 "uniform vec4 ReflectColor;\n"
815 "uniform float ReflectFactor;\n"
816 "uniform float ReflectOffset;\n"
817 "\n"
818 "void main(void)\n"
819 "{\n"
820 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
821 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
822 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
823 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
824 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
825 "       // FIXME temporary hack to detect the case that the reflection\n"
826 "       // gets blackened at edges due to leaving the area that contains actual\n"
827 "       // content.\n"
828 "       // Remove this 'ack once we have a better way to stop this thing from\n"
829 "       // 'appening.\n"
830 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
831 "       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 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
835 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\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 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
840 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
841 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
842 "}\n"
843 "#endif\n"
844 "#else // !MODE_WATER\n"
845 "\n"
846 "\n"
847 "\n"
848 "\n"
849 "// common definitions between vertex shader and fragment shader:\n"
850 "\n"
851 "varying vec2 TexCoord;\n"
852 "#ifdef USEVERTEXTEXTUREBLEND\n"
853 "varying vec2 TexCoord2;\n"
854 "#endif\n"
855 "#ifdef USELIGHTMAP\n"
856 "varying vec2 TexCoordLightmap;\n"
857 "#endif\n"
858 "\n"
859 "#ifdef MODE_LIGHTSOURCE\n"
860 "varying vec3 CubeVector;\n"
861 "#endif\n"
862 "\n"
863 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
864 "varying vec3 LightVector;\n"
865 "#endif\n"
866 "\n"
867 "#ifdef USEEYEVECTOR\n"
868 "varying vec3 EyeVector;\n"
869 "#endif\n"
870 "#ifdef USEFOG\n"
871 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
872 "#endif\n"
873 "\n"
874 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
875 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
876 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
877 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
878 "#endif\n"
879 "\n"
880 "#ifdef USEREFLECTION\n"
881 "varying vec4 ModelViewProjectionPosition;\n"
882 "#endif\n"
883 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
884 "uniform vec3 LightPosition;\n"
885 "varying vec4 ModelViewPosition;\n"
886 "#endif\n"
887 "\n"
888 "#ifdef MODE_LIGHTSOURCE\n"
889 "uniform vec3 LightPosition;\n"
890 "#endif\n"
891 "uniform vec3 EyePosition;\n"
892 "#ifdef MODE_LIGHTDIRECTION\n"
893 "uniform vec3 LightDir;\n"
894 "#endif\n"
895 "uniform vec4 FogPlane;\n"
896 "\n"
897 "#ifdef USESHADOWMAPORTHO\n"
898 "varying vec3 ShadowMapTC;\n"
899 "#endif\n"
900 "\n"
901 "\n"
902 "\n"
903 "\n"
904 "\n"
905 "// 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"
906 "\n"
907 "// fragment shader specific:\n"
908 "#ifdef FRAGMENT_SHADER\n"
909 "\n"
910 "uniform sampler2D Texture_Normal;\n"
911 "uniform sampler2D Texture_Color;\n"
912 "uniform sampler2D Texture_Gloss;\n"
913 "#ifdef USEGLOW\n"
914 "uniform sampler2D Texture_Glow;\n"
915 "#endif\n"
916 "#ifdef USEVERTEXTEXTUREBLEND\n"
917 "uniform sampler2D Texture_SecondaryNormal;\n"
918 "uniform sampler2D Texture_SecondaryColor;\n"
919 "uniform sampler2D Texture_SecondaryGloss;\n"
920 "#ifdef USEGLOW\n"
921 "uniform sampler2D Texture_SecondaryGlow;\n"
922 "#endif\n"
923 "#endif\n"
924 "#ifdef USECOLORMAPPING\n"
925 "uniform sampler2D Texture_Pants;\n"
926 "uniform sampler2D Texture_Shirt;\n"
927 "#endif\n"
928 "#ifdef USEFOG\n"
929 "uniform sampler2D Texture_FogMask;\n"
930 "#endif\n"
931 "#ifdef USELIGHTMAP\n"
932 "uniform sampler2D Texture_Lightmap;\n"
933 "#endif\n"
934 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
935 "uniform sampler2D Texture_Deluxemap;\n"
936 "#endif\n"
937 "#ifdef USEREFLECTION\n"
938 "uniform sampler2D Texture_Reflection;\n"
939 "#endif\n"
940 "\n"
941 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
942 "uniform sampler2D Texture_ScreenDepth;\n"
943 "uniform sampler2D Texture_ScreenNormalMap;\n"
944 "#endif\n"
945 "#ifdef USEDEFERREDLIGHTMAP\n"
946 "uniform sampler2D Texture_ScreenDiffuse;\n"
947 "uniform sampler2D Texture_ScreenSpecular;\n"
948 "#endif\n"
949 "\n"
950 "uniform myhalf3 Color_Pants;\n"
951 "uniform myhalf3 Color_Shirt;\n"
952 "uniform myhalf3 FogColor;\n"
953 "\n"
954 "#ifdef USEFOG\n"
955 "uniform float FogRangeRecip;\n"
956 "uniform float FogPlaneViewDist;\n"
957 "uniform float FogHeightFade;\n"
958 "float FogVertex(void)\n"
959 "{\n"
960 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
961 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
962 "       float fogfrac;\n"
963 "#ifdef USEFOGOUTSIDE\n"
964 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
965 "#else\n"
966 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
967 "#endif\n"
968 "       return float(texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
969 "}\n"
970 "#endif\n"
971 "\n"
972 "#ifdef USEOFFSETMAPPING\n"
973 "uniform float OffsetMapping_Scale;\n"
974 "vec2 OffsetMapping(vec2 TexCoord)\n"
975 "{\n"
976 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
977 "       // 14 sample relief mapping: linear search and then binary search\n"
978 "       // this basically steps forward a small amount repeatedly until it finds\n"
979 "       // itself inside solid, then jitters forward and back using decreasing\n"
980 "       // amounts to find the impact\n"
981 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
982 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
983 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
984 "       vec3 RT = vec3(TexCoord, 1);\n"
985 "       OffsetVector *= 0.1;\n"
986 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
996 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
997 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
998 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
999 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1000 "       return RT.xy;\n"
1001 "#else\n"
1002 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1003 "       // this basically moves forward the full distance, and then backs up based\n"
1004 "       // on height of samples\n"
1005 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1006 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1007 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1008 "       TexCoord += OffsetVector;\n"
1009 "       OffsetVector *= 0.333;\n"
1010 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1011 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1012 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1013 "       return TexCoord;\n"
1014 "#endif\n"
1015 "}\n"
1016 "#endif // USEOFFSETMAPPING\n"
1017 "\n"
1018 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1019 "uniform sampler2D Texture_Attenuation;\n"
1020 "uniform samplerCube Texture_Cube;\n"
1021 "\n"
1022 "#ifdef USESHADOWMAPRECT\n"
1023 "# ifdef USESHADOWSAMPLER\n"
1024 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1025 "# else\n"
1026 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1027 "# endif\n"
1028 "#endif\n"
1029 "\n"
1030 "#ifdef USESHADOWMAP2D\n"
1031 "# ifdef USESHADOWSAMPLER\n"
1032 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1033 "# else\n"
1034 "uniform sampler2D Texture_ShadowMap2D;\n"
1035 "# endif\n"
1036 "#endif\n"
1037 "\n"
1038 "#ifdef USESHADOWMAPVSDCT\n"
1039 "uniform samplerCube Texture_CubeProjection;\n"
1040 "#endif\n"
1041 "\n"
1042 "#ifdef USESHADOWMAPCUBE\n"
1043 "# ifdef USESHADOWSAMPLER\n"
1044 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1045 "# else\n"
1046 "uniform samplerCube Texture_ShadowMapCube;\n"
1047 "# endif\n"
1048 "#endif\n"
1049 "\n"
1050 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1051 "uniform vec2 ShadowMap_TextureScale;\n"
1052 "uniform vec4 ShadowMap_Parameters;\n"
1053 "#endif\n"
1054 "\n"
1055 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1056 "# ifdef USESHADOWMAPORTHO\n"
1057 "#  define GetShadowMapTC2D(dir) (min(dir, vec3(ShadowMap_Parameters.zw, 1.0)))\n"
1058 "# else\n"
1059 "#  ifdef USESHADOWMAPVSDCT\n"
1060 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1061 "{\n"
1062 "   vec3 adir = abs(dir);\n"
1063 "   vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1064 "   float ma = max(max(adir.x, adir.y), adir.z);\n"
1065 "   vec3 stc = vec3(mix(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1066 "   stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
1067 "   stc.z += ShadowMap_Parameters.z;\n"
1068 "   return stc;\n"
1069 "}\n"
1070 "#  else\n"
1071 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1072 "{\n"
1073 "       vec3 adir = abs(dir);\n"
1074 "       vec2 tc;\n"
1075 "       vec2 offset;\n"
1076 "       float ma;\n"
1077 "       if (adir.x > adir.y)\n"
1078 "       {\n"
1079 "               if (adir.x > adir.z) // X\n"
1080 "               {\n"
1081 "                       ma = adir.x;\n"
1082 "                       tc = dir.zy;\n"
1083 "                       offset = vec2(mix(0.5, 1.5, dir.x < 0.0), 0.5);\n"
1084 "               }\n"
1085 "               else // Z\n"
1086 "               {\n"
1087 "                       ma = adir.z;\n"
1088 "                       tc = dir.xy;\n"
1089 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1090 "               }\n"
1091 "       }\n"
1092 "       else\n"
1093 "       {\n"
1094 "               if (adir.y > adir.z) // Y\n"
1095 "               {\n"
1096 "                       ma = adir.y;\n"
1097 "                       tc = dir.xz;\n"
1098 "                       offset = vec2(mix(0.5, 1.5, dir.y < 0.0), 1.5);\n"
1099 "               }\n"
1100 "               else // Z\n"
1101 "               {\n"
1102 "                       ma = adir.z;\n"
1103 "                       tc = dir.xy;\n"
1104 "                       offset = vec2(mix(0.5, 1.5, dir.z < 0.0), 2.5);\n"
1105 "               }\n"
1106 "       }\n"
1107 "\n"
1108 "       vec3 stc = vec3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
1109 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
1110 "       stc.z += ShadowMap_Parameters.z;\n"
1111 "       return stc;\n"
1112 "}\n"
1113 "#  endif\n"
1114 "# endif\n"
1115 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1116 "\n"
1117 "#ifdef USESHADOWMAPCUBE\n"
1118 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1119 "{\n"
1120 "       vec3 adir = abs(dir);\n"
1121 "       return vec4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
1122 "}\n"
1123 "#endif\n"
1124 "\n"
1125 "# ifdef USESHADOWMAPRECT\n"
1126 "float ShadowMapCompare(vec3 dir)\n"
1127 "{\n"
1128 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1129 "       float f;\n"
1130 "#  ifdef USESHADOWSAMPLER\n"
1131 "\n"
1132 "#    ifdef USESHADOWMAPPCF\n"
1133 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1134 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1135 "#    else\n"
1136 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1137 "#    endif\n"
1138 "\n"
1139 "#  else\n"
1140 "\n"
1141 "#    ifdef USESHADOWMAPPCF\n"
1142 "#      if USESHADOWMAPPCF > 1\n"
1143 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1144 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1145 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1146 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1147 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1148 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1149 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1150 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1151 "#      else\n"
1152 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1153 "       vec2 offset = fract(shadowmaptc.xy);\n"
1154 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1155 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1156 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1157 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1158 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1159 "#      endif\n"
1160 "#    else\n"
1161 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1162 "#    endif\n"
1163 "\n"
1164 "#  endif\n"
1165 "#  ifdef USESHADOWMAPORTHO\n"
1166 "       return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
1167 "#  else\n"
1168 "       return f;\n"
1169 "#  endif\n"
1170 "}\n"
1171 "# endif\n"
1172 "\n"
1173 "# ifdef USESHADOWMAP2D\n"
1174 "float ShadowMapCompare(vec3 dir)\n"
1175 "{\n"
1176 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1177 "       float f;\n"
1178 "\n"
1179 "#  ifdef USESHADOWSAMPLER\n"
1180 "#    ifdef USESHADOWMAPPCF\n"
1181 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1182 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1183 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1184 "#    else\n"
1185 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1186 "#    endif\n"
1187 "#  else\n"
1188 "#    ifdef USESHADOWMAPPCF\n"
1189 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1190 "#      ifdef GL_ARB_texture_gather\n"
1191 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1192 "#      else\n"
1193 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1194 "#      endif\n"
1195 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1196 "       center *= ShadowMap_TextureScale;\n"
1197 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1198 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1199 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1200 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1201 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1202 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1203 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1204 "#     else\n"
1205 "#      ifdef GL_EXT_gpu_shader4\n"
1206 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1207 "#      else\n"
1208 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1209 "#      endif\n"
1210 "#      if USESHADOWMAPPCF > 1\n"
1211 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1212 "       center *= ShadowMap_TextureScale;\n"
1213 "       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"
1214 "       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"
1215 "       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"
1216 "       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"
1217 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1218 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1219 "#      else\n"
1220 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1221 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1222 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1223 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1224 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1225 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1226 "#      endif\n"
1227 "#     endif\n"
1228 "#    else\n"
1229 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1230 "#    endif\n"
1231 "#  endif\n"
1232 "#  ifdef USESHADOWMAPORTHO\n"
1233 "       return mix(ShadowMap_Parameters.x, ShadowMap_Parameters.y, f);\n"
1234 "#  else\n"
1235 "       return f;\n"
1236 "#  endif\n"
1237 "}\n"
1238 "# endif\n"
1239 "\n"
1240 "# ifdef USESHADOWMAPCUBE\n"
1241 "float ShadowMapCompare(vec3 dir)\n"
1242 "{\n"
1243 "       // apply depth texture cubemap as light filter\n"
1244 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1245 "       float f;\n"
1246 "#  ifdef USESHADOWSAMPLER\n"
1247 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1248 "#  else\n"
1249 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1250 "#  endif\n"
1251 "       return f;\n"
1252 "}\n"
1253 "# endif\n"
1254 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1255 "#endif // FRAGMENT_SHADER\n"
1256 "\n"
1257 "\n"
1258 "\n"
1259 "\n"
1260 "#ifdef MODE_DEFERREDGEOMETRY\n"
1261 "#ifdef VERTEX_SHADER\n"
1262 "uniform mat4 TexMatrix;\n"
1263 "#ifdef USEVERTEXTEXTUREBLEND\n"
1264 "uniform mat4 BackgroundTexMatrix;\n"
1265 "#endif\n"
1266 "uniform mat4 ModelViewMatrix;\n"
1267 "void main(void)\n"
1268 "{\n"
1269 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1270 "#ifdef USEVERTEXTEXTUREBLEND\n"
1271 "       gl_FrontColor = gl_Color;\n"
1272 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1273 "#endif\n"
1274 "\n"
1275 "       // transform unnormalized eye direction into tangent space\n"
1276 "#ifdef USEOFFSETMAPPING\n"
1277 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1278 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1279 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1280 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1281 "#endif\n"
1282 "\n"
1283 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1284 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1285 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1286 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1287 "}\n"
1288 "#endif // VERTEX_SHADER\n"
1289 "\n"
1290 "#ifdef FRAGMENT_SHADER\n"
1291 "void main(void)\n"
1292 "{\n"
1293 "#ifdef USEOFFSETMAPPING\n"
1294 "       // apply offsetmapping\n"
1295 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1296 "#define TexCoord TexCoordOffset\n"
1297 "#endif\n"
1298 "\n"
1299 "#ifdef USEALPHAKILL\n"
1300 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1301 "               discard;\n"
1302 "#endif\n"
1303 "\n"
1304 "#ifdef USEVERTEXTEXTUREBLEND\n"
1305 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1306 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1307 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1308 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1309 "#endif\n"
1310 "\n"
1311 "#ifdef USEVERTEXTEXTUREBLEND\n"
1312 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1313 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1314 "#else\n"
1315 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1316 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1317 "#endif\n"
1318 "\n"
1319 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1320 "}\n"
1321 "#endif // FRAGMENT_SHADER\n"
1322 "#else // !MODE_DEFERREDGEOMETRY\n"
1323 "\n"
1324 "\n"
1325 "\n"
1326 "\n"
1327 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1328 "#ifdef VERTEX_SHADER\n"
1329 "uniform mat4 ModelViewMatrix;\n"
1330 "void main(void)\n"
1331 "{\n"
1332 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1333 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1334 "}\n"
1335 "#endif // VERTEX_SHADER\n"
1336 "\n"
1337 "#ifdef FRAGMENT_SHADER\n"
1338 "uniform mat4 ViewToLight;\n"
1339 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1340 "uniform vec2 ScreenToDepth;\n"
1341 "uniform myhalf3 DeferredColor_Ambient;\n"
1342 "uniform myhalf3 DeferredColor_Diffuse;\n"
1343 "#ifdef USESPECULAR\n"
1344 "uniform myhalf3 DeferredColor_Specular;\n"
1345 "uniform myhalf SpecularPower;\n"
1346 "#endif\n"
1347 "uniform myhalf2 PixelToScreenTexCoord;\n"
1348 "void main(void)\n"
1349 "{\n"
1350 "       // calculate viewspace pixel position\n"
1351 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1352 "       vec3 position;\n"
1353 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1354 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1355 "       // decode viewspace pixel normal\n"
1356 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1357 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1358 "       // surfacenormal = pixel normal in viewspace\n"
1359 "       // LightVector = pixel to light in viewspace\n"
1360 "       // CubeVector = position in lightspace\n"
1361 "       // eyevector = pixel to view in viewspace\n"
1362 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1363 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1364 "#ifdef USEDIFFUSE\n"
1365 "       // calculate diffuse shading\n"
1366 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1367 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1368 "#endif\n"
1369 "#ifdef USESPECULAR\n"
1370 "       // calculate directional shading\n"
1371 "       vec3 eyevector = position * -1.0;\n"
1372 "#  ifdef USEEXACTSPECULARMATH\n"
1373 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1374 "#  else\n"
1375 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1376 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1377 "#  endif\n"
1378 "#endif\n"
1379 "\n"
1380 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1381 "       fade *= ShadowMapCompare(CubeVector);\n"
1382 "#endif\n"
1383 "\n"
1384 "#ifdef USEDIFFUSE\n"
1385 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1386 "#else\n"
1387 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1388 "#endif\n"
1389 "#ifdef USESPECULAR\n"
1390 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1391 "#else\n"
1392 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1393 "#endif\n"
1394 "\n"
1395 "# ifdef USECUBEFILTER\n"
1396 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1397 "       gl_FragData[0].rgb *= cubecolor;\n"
1398 "       gl_FragData[1].rgb *= cubecolor;\n"
1399 "# endif\n"
1400 "}\n"
1401 "#endif // FRAGMENT_SHADER\n"
1402 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1403 "\n"
1404 "\n"
1405 "\n"
1406 "\n"
1407 "#ifdef VERTEX_SHADER\n"
1408 "uniform mat4 TexMatrix;\n"
1409 "#ifdef USEVERTEXTEXTUREBLEND\n"
1410 "uniform mat4 BackgroundTexMatrix;\n"
1411 "#endif\n"
1412 "#ifdef MODE_LIGHTSOURCE\n"
1413 "uniform mat4 ModelToLight;\n"
1414 "#endif\n"
1415 "#ifdef USESHADOWMAPORTHO\n"
1416 "uniform mat4 ShadowMapMatrix;\n"
1417 "#endif\n"
1418 "void main(void)\n"
1419 "{\n"
1420 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1421 "       gl_FrontColor = gl_Color;\n"
1422 "#endif\n"
1423 "       // copy the surface texcoord\n"
1424 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1425 "#ifdef USEVERTEXTEXTUREBLEND\n"
1426 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1427 "#endif\n"
1428 "#ifdef USELIGHTMAP\n"
1429 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1430 "#endif\n"
1431 "\n"
1432 "#ifdef MODE_LIGHTSOURCE\n"
1433 "       // transform vertex position into light attenuation/cubemap space\n"
1434 "       // (-1 to +1 across the light box)\n"
1435 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1436 "\n"
1437 "# ifdef USEDIFFUSE\n"
1438 "       // transform unnormalized light direction into tangent space\n"
1439 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1440 "       //  normalize it per pixel)\n"
1441 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1442 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1443 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1444 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1445 "# endif\n"
1446 "#endif\n"
1447 "\n"
1448 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1449 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1450 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1451 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1452 "#endif\n"
1453 "\n"
1454 "       // transform unnormalized eye direction into tangent space\n"
1455 "#ifdef USEEYEVECTOR\n"
1456 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1457 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1458 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1459 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1460 "#endif\n"
1461 "\n"
1462 "#ifdef USEFOG\n"
1463 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1464 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1465 "#endif\n"
1466 "\n"
1467 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1468 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1469 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1470 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1471 "#endif\n"
1472 "\n"
1473 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1474 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1475 "\n"
1476 "#ifdef USESHADOWMAPORTHO\n"
1477 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1478 "#endif\n"
1479 "\n"
1480 "#ifdef USEREFLECTION\n"
1481 "       ModelViewProjectionPosition = gl_Position;\n"
1482 "#endif\n"
1483 "}\n"
1484 "#endif // VERTEX_SHADER\n"
1485 "\n"
1486 "\n"
1487 "\n"
1488 "\n"
1489 "#ifdef FRAGMENT_SHADER\n"
1490 "#ifdef USEDEFERREDLIGHTMAP\n"
1491 "uniform myhalf2 PixelToScreenTexCoord;\n"
1492 "uniform myhalf3 DeferredMod_Diffuse;\n"
1493 "uniform myhalf3 DeferredMod_Specular;\n"
1494 "#endif\n"
1495 "uniform myhalf3 Color_Ambient;\n"
1496 "uniform myhalf3 Color_Diffuse;\n"
1497 "uniform myhalf3 Color_Specular;\n"
1498 "uniform myhalf SpecularPower;\n"
1499 "#ifdef USEGLOW\n"
1500 "uniform myhalf3 Color_Glow;\n"
1501 "#endif\n"
1502 "uniform myhalf Alpha;\n"
1503 "#ifdef USEREFLECTION\n"
1504 "uniform vec4 DistortScaleRefractReflect;\n"
1505 "uniform vec4 ScreenScaleRefractReflect;\n"
1506 "uniform vec4 ScreenCenterRefractReflect;\n"
1507 "uniform myhalf4 ReflectColor;\n"
1508 "#endif\n"
1509 "#ifdef USEREFLECTCUBE\n"
1510 "uniform mat4 ModelToReflectCube;\n"
1511 "uniform sampler2D Texture_ReflectMask;\n"
1512 "uniform samplerCube Texture_ReflectCube;\n"
1513 "#endif\n"
1514 "#ifdef MODE_LIGHTDIRECTION\n"
1515 "uniform myhalf3 LightColor;\n"
1516 "#endif\n"
1517 "#ifdef MODE_LIGHTSOURCE\n"
1518 "uniform myhalf3 LightColor;\n"
1519 "#endif\n"
1520 "void main(void)\n"
1521 "{\n"
1522 "#ifdef USEOFFSETMAPPING\n"
1523 "       // apply offsetmapping\n"
1524 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1525 "#define TexCoord TexCoordOffset\n"
1526 "#endif\n"
1527 "\n"
1528 "       // combine the diffuse textures (base, pants, shirt)\n"
1529 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1530 "#ifdef USEALPHAKILL\n"
1531 "       if (color.a < 0.5)\n"
1532 "               discard;\n"
1533 "#endif\n"
1534 "       color.a *= Alpha;\n"
1535 "#ifdef USECOLORMAPPING\n"
1536 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1537 "#endif\n"
1538 "#ifdef USEVERTEXTEXTUREBLEND\n"
1539 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1540 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1541 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1542 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1543 "       color.a = 1.0;\n"
1544 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1545 "#endif\n"
1546 "\n"
1547 "       // get the surface normal\n"
1548 "#ifdef USEVERTEXTEXTUREBLEND\n"
1549 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1550 "#else\n"
1551 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1552 "#endif\n"
1553 "\n"
1554 "       // get the material colors\n"
1555 "       myhalf3 diffusetex = color.rgb;\n"
1556 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1557 "# ifdef USEVERTEXTEXTUREBLEND\n"
1558 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1559 "# else\n"
1560 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1561 "# endif\n"
1562 "#endif\n"
1563 "\n"
1564 "#ifdef USEREFLECTCUBE\n"
1565 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1566 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1567 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1568 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1569 "#endif\n"
1570 "\n"
1571 "\n"
1572 "\n"
1573 "\n"
1574 "#ifdef MODE_LIGHTSOURCE\n"
1575 "       // light source\n"
1576 "#ifdef USEDIFFUSE\n"
1577 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1578 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1579 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1580 "#ifdef USESPECULAR\n"
1581 "#ifdef USEEXACTSPECULARMATH\n"
1582 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1583 "#else\n"
1584 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1585 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1586 "#endif\n"
1587 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1588 "#endif\n"
1589 "#else\n"
1590 "       color.rgb = diffusetex * Color_Ambient;\n"
1591 "#endif\n"
1592 "       color.rgb *= LightColor;\n"
1593 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1594 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1595 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1596 "#endif\n"
1597 "# ifdef USECUBEFILTER\n"
1598 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1599 "# endif\n"
1600 "#endif // MODE_LIGHTSOURCE\n"
1601 "\n"
1602 "\n"
1603 "\n"
1604 "\n"
1605 "#ifdef MODE_LIGHTDIRECTION\n"
1606 "#define SHADING\n"
1607 "#ifdef USEDIFFUSE\n"
1608 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1609 "#endif\n"
1610 "#define lightcolor LightColor\n"
1611 "#endif // MODE_LIGHTDIRECTION\n"
1612 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1613 "#define SHADING\n"
1614 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1615 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1616 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1617 "       // convert modelspace light vector to tangentspace\n"
1618 "       myhalf3 lightnormal;\n"
1619 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1620 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1621 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1622 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1623 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1624 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1625 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1626 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1627 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1628 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1629 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1630 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1631 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1632 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1633 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1634 "#define SHADING\n"
1635 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1636 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1637 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1638 "#endif\n"
1639 "\n"
1640 "\n"
1641 "\n"
1642 "\n"
1643 "#ifdef MODE_LIGHTMAP\n"
1644 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1645 "#endif // MODE_LIGHTMAP\n"
1646 "#ifdef MODE_VERTEXCOLOR\n"
1647 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1648 "#endif // MODE_VERTEXCOLOR\n"
1649 "#ifdef MODE_FLATCOLOR\n"
1650 "       color.rgb = diffusetex * Color_Ambient;\n"
1651 "#endif // MODE_FLATCOLOR\n"
1652 "\n"
1653 "\n"
1654 "\n"
1655 "\n"
1656 "#ifdef SHADING\n"
1657 "# ifdef USEDIFFUSE\n"
1658 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1659 "#  ifdef USESPECULAR\n"
1660 "#   ifdef USEEXACTSPECULARMATH\n"
1661 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1662 "#   else\n"
1663 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1664 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1665 "#   endif\n"
1666 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1667 "#  else\n"
1668 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1669 "#  endif\n"
1670 "# else\n"
1671 "       color.rgb = diffusetex * Color_Ambient;\n"
1672 "# endif\n"
1673 "#endif\n"
1674 "\n"
1675 "#ifdef USESHADOWMAPORTHO\n"
1676 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1677 "#endif\n"
1678 "\n"
1679 "#ifdef USEDEFERREDLIGHTMAP\n"
1680 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1681 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1682 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1683 "#endif\n"
1684 "\n"
1685 "#ifdef USEGLOW\n"
1686 "#ifdef USEVERTEXTEXTUREBLEND\n"
1687 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1688 "#else\n"
1689 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1690 "#endif\n"
1691 "#endif\n"
1692 "\n"
1693 "#ifdef USEFOG\n"
1694 "#ifdef MODE_LIGHTSOURCE\n"
1695 "       color.rgb *= myhalf(FogVertex());\n"
1696 "#else\n"
1697 "       color.rgb = mix(FogColor, color.rgb, FogVertex());\n"
1698 "#endif\n"
1699 "#endif\n"
1700 "\n"
1701 "       // 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"
1702 "#ifdef USEREFLECTION\n"
1703 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1704 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1705 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1706 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1707 "       // FIXME temporary hack to detect the case that the reflection\n"
1708 "       // gets blackened at edges due to leaving the area that contains actual\n"
1709 "       // content.\n"
1710 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1711 "       // 'appening.\n"
1712 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1713 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1714 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1715 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1716 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1717 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1718 "#endif\n"
1719 "\n"
1720 "       gl_FragColor = vec4(color);\n"
1721 "}\n"
1722 "#endif // FRAGMENT_SHADER\n"
1723 "\n"
1724 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1725 "#endif // !MODE_DEFERREDGEOMETRY\n"
1726 "#endif // !MODE_WATER\n"
1727 "#endif // !MODE_REFRACTION\n"
1728 "#endif // !MODE_BLOOMBLUR\n"
1729 "#endif // !MODE_GENERIC\n"
1730 "#endif // !MODE_POSTPROCESS\n"
1731 "#endif // !MODE_SHOWDEPTH\n"
1732 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1733 ;
1734
1735 /*
1736 =========================================================================================================================================================
1737
1738
1739
1740 =========================================================================================================================================================
1741
1742
1743
1744 =========================================================================================================================================================
1745
1746
1747
1748 =========================================================================================================================================================
1749
1750
1751
1752 =========================================================================================================================================================
1753
1754
1755
1756 =========================================================================================================================================================
1757
1758
1759
1760 =========================================================================================================================================================
1761 */
1762
1763 const char *builtincgshaderstring =
1764 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1765 "// written by Forest 'LordHavoc' Hale\n"
1766 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1767 "\n"
1768 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE)\n"
1769 "# define USEFOG\n"
1770 "#endif\n"
1771 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1772 "#define USELIGHTMAP\n"
1773 "#endif\n"
1774 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1775 "#define USEEYEVECTOR\n"
1776 "#endif\n"
1777 "\n"
1778 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1779 "#ifdef VERTEX_SHADER\n"
1780 "void main\n"
1781 "(\n"
1782 "float4 gl_Vertex : POSITION,\n"
1783 "uniform float4x4 ModelViewProjectionMatrix,\n"
1784 "out float4 gl_Position : POSITION\n"
1785 ")\n"
1786 "{\n"
1787 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1788 "}\n"
1789 "#endif\n"
1790 "#else // !MODE_DEPTH_ORSHADOW\n"
1791 "\n"
1792 "\n"
1793 "\n"
1794 "\n"
1795 "#ifdef MODE_SHOWDEPTH\n"
1796 "#ifdef VERTEX_SHADER\n"
1797 "void main\n"
1798 "(\n"
1799 "float4 gl_Vertex : POSITION,\n"
1800 "uniform float4x4 ModelViewProjectionMatrix,\n"
1801 "out float4 gl_Position : POSITION,\n"
1802 "out float4 gl_FrontColor : COLOR0\n"
1803 ")\n"
1804 "{\n"
1805 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1806 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1807 "}\n"
1808 "#endif\n"
1809 "\n"
1810 "#ifdef FRAGMENT_SHADER\n"
1811 "void main\n"
1812 "(\n"
1813 "float4 gl_FrontColor : COLOR0,\n"
1814 "out float4 gl_FragColor : COLOR\n"
1815 ")\n"
1816 "{\n"
1817 "       gl_FragColor = gl_FrontColor;\n"
1818 "}\n"
1819 "#endif\n"
1820 "#else // !MODE_SHOWDEPTH\n"
1821 "\n"
1822 "\n"
1823 "\n"
1824 "\n"
1825 "#ifdef MODE_POSTPROCESS\n"
1826 "\n"
1827 "#ifdef VERTEX_SHADER\n"
1828 "void main\n"
1829 "(\n"
1830 "float4 gl_Vertex : POSITION,\n"
1831 "uniform float4x4 ModelViewProjectionMatrix,\n"
1832 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1833 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1834 "out float4 gl_Position : POSITION,\n"
1835 "out float2 TexCoord1 : TEXCOORD0,\n"
1836 "out float2 TexCoord2 : TEXCOORD1\n"
1837 ")\n"
1838 "{\n"
1839 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1840 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1841 "#ifdef USEBLOOM\n"
1842 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1843 "#endif\n"
1844 "}\n"
1845 "#endif\n"
1846 "\n"
1847 "#ifdef FRAGMENT_SHADER\n"
1848 "void main\n"
1849 "(\n"
1850 "float2 TexCoord1 : TEXCOORD0,\n"
1851 "float2 TexCoord2 : TEXCOORD1,\n"
1852 "uniform sampler2D Texture_First,\n"
1853 "#ifdef USEBLOOM\n"
1854 "uniform sampler2D Texture_Second,\n"
1855 "#endif\n"
1856 "#ifdef USEGAMMARAMPS\n"
1857 "uniform sampler2D Texture_GammaRamps,\n"
1858 "#endif\n"
1859 "#ifdef USESATURATION\n"
1860 "uniform float Saturation,\n"
1861 "#endif\n"
1862 "#ifdef USEVIEWTINT\n"
1863 "uniform float4 ViewTintColor,\n"
1864 "#endif\n"
1865 "uniform float4 UserVec1,\n"
1866 "uniform float4 UserVec2,\n"
1867 "uniform float4 UserVec3,\n"
1868 "uniform float4 UserVec4,\n"
1869 "uniform float ClientTime,\n"
1870 "uniform float2 PixelSize,\n"
1871 "out float4 gl_FragColor : COLOR\n"
1872 ")\n"
1873 "{\n"
1874 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1875 "#ifdef USEBLOOM\n"
1876 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1877 "#endif\n"
1878 "#ifdef USEVIEWTINT\n"
1879 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1880 "#endif\n"
1881 "\n"
1882 "#ifdef USEPOSTPROCESSING\n"
1883 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1884 "// 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"
1885 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1886 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1887 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1888 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1889 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1890 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1891 "#endif\n"
1892 "\n"
1893 "#ifdef USESATURATION\n"
1894 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1895 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1896 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1897 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1898 "#endif\n"
1899 "\n"
1900 "#ifdef USEGAMMARAMPS\n"
1901 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1902 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1903 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1904 "#endif\n"
1905 "}\n"
1906 "#endif\n"
1907 "#else // !MODE_POSTPROCESS\n"
1908 "\n"
1909 "\n"
1910 "\n"
1911 "\n"
1912 "#ifdef MODE_GENERIC\n"
1913 "#ifdef VERTEX_SHADER\n"
1914 "void main\n"
1915 "(\n"
1916 "float4 gl_Vertex : POSITION,\n"
1917 "uniform float4x4 ModelViewProjectionMatrix,\n"
1918 "float4 gl_Color : COLOR0,\n"
1919 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1920 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1921 "out float4 gl_Position : POSITION,\n"
1922 "out float4 gl_FrontColor : COLOR,\n"
1923 "out float2 TexCoord1 : TEXCOORD0,\n"
1924 "out float2 TexCoord2 : TEXCOORD1\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FrontColor = gl_Color;\n"
1928 "#ifdef USEDIFFUSE\n"
1929 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1930 "#endif\n"
1931 "#ifdef USESPECULAR\n"
1932 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1933 "#endif\n"
1934 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1935 "}\n"
1936 "#endif\n"
1937 "\n"
1938 "#ifdef FRAGMENT_SHADER\n"
1939 "\n"
1940 "void main\n"
1941 "(\n"
1942 "float4 gl_FrontColor : COLOR,\n"
1943 "float2 TexCoord1 : TEXCOORD0,\n"
1944 "float2 TexCoord2 : TEXCOORD1,\n"
1945 "#ifdef USEDIFFUSE\n"
1946 "uniform sampler2D Texture_First,\n"
1947 "#endif\n"
1948 "#ifdef USESPECULAR\n"
1949 "uniform sampler2D Texture_Second,\n"
1950 "#endif\n"
1951 "out float4 gl_FragColor : COLOR\n"
1952 ")\n"
1953 "{\n"
1954 "       gl_FragColor = gl_FrontColor;\n"
1955 "#ifdef USEDIFFUSE\n"
1956 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
1957 "#endif\n"
1958 "\n"
1959 "#ifdef USESPECULAR\n"
1960 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
1961 "# ifdef USECOLORMAPPING\n"
1962 "       gl_FragColor *= tex2;\n"
1963 "# endif\n"
1964 "# ifdef USEGLOW\n"
1965 "       gl_FragColor += tex2;\n"
1966 "# endif\n"
1967 "# ifdef USEVERTEXTEXTUREBLEND\n"
1968 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
1969 "# endif\n"
1970 "#endif\n"
1971 "}\n"
1972 "#endif\n"
1973 "#else // !MODE_GENERIC\n"
1974 "\n"
1975 "\n"
1976 "\n"
1977 "\n"
1978 "#ifdef MODE_BLOOMBLUR\n"
1979 "#ifdef VERTEX_SHADER\n"
1980 "void main\n"
1981 "(\n"
1982 "float4 gl_Vertex : POSITION,\n"
1983 "uniform float4x4 ModelViewProjectionMatrix,\n"
1984 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1985 "out float4 gl_Position : POSITION,\n"
1986 "out float2 TexCoord : TEXCOORD0\n"
1987 ")\n"
1988 "{\n"
1989 "       TexCoord = gl_MultiTexCoord0.xy;\n"
1990 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "\n"
1996 "void main\n"
1997 "(\n"
1998 "float2 TexCoord : TEXCOORD0,\n"
1999 "uniform sampler2D Texture_First,\n"
2000 "uniform float4 BloomBlur_Parameters,\n"
2001 "out float4 gl_FragColor : COLOR\n"
2002 ")\n"
2003 "{\n"
2004 "       int i;\n"
2005 "       float2 tc = TexCoord;\n"
2006 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2007 "       tc += BloomBlur_Parameters.xy;\n"
2008 "       for (i = 1;i < SAMPLES;i++)\n"
2009 "       {\n"
2010 "               color += tex2D(Texture_First, tc).rgb;\n"
2011 "               tc += BloomBlur_Parameters.xy;\n"
2012 "       }\n"
2013 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2014 "}\n"
2015 "#endif\n"
2016 "#else // !MODE_BLOOMBLUR\n"
2017 "#ifdef MODE_REFRACTION\n"
2018 "#ifdef VERTEX_SHADER\n"
2019 "void main\n"
2020 "(\n"
2021 "float4 gl_Vertex : POSITION,\n"
2022 "uniform float4x4 ModelViewProjectionMatrix,\n"
2023 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2024 "uniform float4x4 TexMatrix,\n"
2025 "uniform float3 EyePosition,\n"
2026 "out float4 gl_Position : POSITION,\n"
2027 "out float2 TexCoord : TEXCOORD0,\n"
2028 "out float3 EyeVector : TEXCOORD1,\n"
2029 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2030 ")\n"
2031 "{\n"
2032 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2033 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2034 "       ModelViewProjectionPosition = gl_Position;\n"
2035 "}\n"
2036 "#endif\n"
2037 "\n"
2038 "#ifdef FRAGMENT_SHADER\n"
2039 "void main\n"
2040 "(\n"
2041 "float2 TexCoord : TEXCOORD0,\n"
2042 "float3 EyeVector : TEXCOORD1,\n"
2043 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2044 "uniform sampler2D Texture_Normal,\n"
2045 "uniform sampler2D Texture_Refraction,\n"
2046 "uniform sampler2D Texture_Reflection,\n"
2047 "uniform float4 DistortScaleRefractReflect,\n"
2048 "uniform float4 ScreenScaleRefractReflect,\n"
2049 "uniform float4 ScreenCenterRefractReflect,\n"
2050 "uniform float4 RefractColor,\n"
2051 "out float4 gl_FragColor : COLOR\n"
2052 ")\n"
2053 "{\n"
2054 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2055 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2056 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2057 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2058 "       // FIXME temporary hack to detect the case that the reflection\n"
2059 "       // gets blackened at edges due to leaving the area that contains actual\n"
2060 "       // content.\n"
2061 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2062 "       // 'appening.\n"
2063 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2064 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2065 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2066 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2067 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2068 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2069 "}\n"
2070 "#endif\n"
2071 "#else // !MODE_REFRACTION\n"
2072 "\n"
2073 "\n"
2074 "\n"
2075 "\n"
2076 "#ifdef MODE_WATER\n"
2077 "#ifdef VERTEX_SHADER\n"
2078 "\n"
2079 "void main\n"
2080 "(\n"
2081 "float4 gl_Vertex : POSITION,\n"
2082 "uniform float4x4 ModelViewProjectionMatrix,\n"
2083 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2084 "uniform float4x4 TexMatrix,\n"
2085 "uniform float3 EyePosition,\n"
2086 "out float4 gl_Position : POSITION,\n"
2087 "out float2 TexCoord : TEXCOORD0,\n"
2088 "out float3 EyeVector : TEXCOORD1,\n"
2089 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2090 ")\n"
2091 "{\n"
2092 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2093 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2094 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2095 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2096 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2097 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2098 "       ModelViewProjectionPosition = gl_Position;\n"
2099 "}\n"
2100 "#endif\n"
2101 "\n"
2102 "#ifdef FRAGMENT_SHADER\n"
2103 "void main\n"
2104 "(\n"
2105 "float2 TexCoord : TEXCOORD0,\n"
2106 "float3 EyeVector : TEXCOORD1,\n"
2107 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2108 "uniform sampler2D Texture_Normal,\n"
2109 "uniform sampler2D Texture_Refraction,\n"
2110 "uniform sampler2D Texture_Reflection,\n"
2111 "uniform float4 DistortScaleRefractReflect,\n"
2112 "uniform float4 ScreenScaleRefractReflect,\n"
2113 "uniform float4 ScreenCenterRefractReflect,\n"
2114 "uniform float4 RefractColor,\n"
2115 "uniform float4 ReflectColor,\n"
2116 "uniform float ReflectFactor,\n"
2117 "uniform float ReflectOffset,\n"
2118 "out float4 gl_FragColor : COLOR\n"
2119 ")\n"
2120 "{\n"
2121 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2122 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2123 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2124 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2125 "       // FIXME temporary hack to detect the case that the reflection\n"
2126 "       // gets blackened at edges due to leaving the area that contains actual\n"
2127 "       // content.\n"
2128 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2129 "       // 'appening.\n"
2130 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2131 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2132 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2133 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2134 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2135 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2136 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2137 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2138 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2139 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2140 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2141 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2142 "}\n"
2143 "#endif\n"
2144 "#else // !MODE_WATER\n"
2145 "\n"
2146 "\n"
2147 "\n"
2148 "\n"
2149 "// 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"
2150 "\n"
2151 "// fragment shader specific:\n"
2152 "#ifdef FRAGMENT_SHADER\n"
2153 "\n"
2154 "#ifdef USEFOG\n"
2155 "float FogVertex(float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask)\n"
2156 "{\n"
2157 "       float fogfrac;\n"
2158 "#ifdef USEFOGOUTSIDE\n"
2159 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2160 "#else\n"
2161 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2162 "#endif\n"
2163 "       return float(tex2D(Texture_FogMask, half2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)));\n"
2164 "}\n"
2165 "#endif\n"
2166 "\n"
2167 "#ifdef USEOFFSETMAPPING\n"
2168 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2169 "{\n"
2170 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2171 "       // 14 sample relief mapping: linear search and then binary search\n"
2172 "       // this basically steps forward a small amount repeatedly until it finds\n"
2173 "       // itself inside solid, then jitters forward and back using decreasing\n"
2174 "       // amounts to find the impact\n"
2175 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2176 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2177 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2178 "       float3 RT = float3(TexCoord, 1);\n"
2179 "       OffsetVector *= 0.1;\n"
2180 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2181 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2182 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2183 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2184 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2185 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2186 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2187 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2188 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2189 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2190 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2191 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2192 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2193 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2194 "       return RT.xy;\n"
2195 "#else\n"
2196 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2197 "       // this basically moves forward the full distance, and then backs up based\n"
2198 "       // on height of samples\n"
2199 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2200 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2201 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2202 "       TexCoord += OffsetVector;\n"
2203 "       OffsetVector *= 0.333;\n"
2204 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2205 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2206 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2207 "       return TexCoord;\n"
2208 "#endif\n"
2209 "}\n"
2210 "#endif // USEOFFSETMAPPING\n"
2211 "\n"
2212 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2213 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2214 "# ifdef USESHADOWMAPVSDCT\n"
2215 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2216 "{\n"
2217 "   float3 adir = abs(dir);\n"
2218 "   float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2219 "   float ma = max(max(adir.x, adir.y), adir.z);\n"
2220 "   float3 stc = float3(lerp(dir.xy, dir.zz, proj.xy) * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2221 "   stc.xy += proj.zw * ShadowMap_Parameters.y;\n"
2222 "   stc.z += ShadowMap_Parameters.z;\n"
2223 "   return stc;\n"
2224 "}\n"
2225 "# else\n"
2226 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2227 "{\n"
2228 "       float3 adir = abs(dir);\n"
2229 "       float2 tc;\n"
2230 "       float2 offset;\n"
2231 "       float ma;\n"
2232 "       if (adir.x > adir.y)\n"
2233 "       {\n"
2234 "               if (adir.x > adir.z) // X\n"
2235 "               {\n"
2236 "                       ma = adir.x;\n"
2237 "                       tc = dir.zy;\n"
2238 "                       offset = float2(lerp(0.5, 1.5, dir.x < 0.0), 0.5);\n"
2239 "               }\n"
2240 "               else // Z\n"
2241 "               {\n"
2242 "                       ma = adir.z;\n"
2243 "                       tc = dir.xy;\n"
2244 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2245 "               }\n"
2246 "       }\n"
2247 "       else\n"
2248 "       {\n"
2249 "               if (adir.y > adir.z) // Y\n"
2250 "               {\n"
2251 "                       ma = adir.y;\n"
2252 "                       tc = dir.xz;\n"
2253 "                       offset = float2(lerp(0.5, 1.5, dir.y < 0.0), 1.5);\n"
2254 "               }\n"
2255 "               else // Z\n"
2256 "               {\n"
2257 "                       ma = adir.z;\n"
2258 "                       tc = dir.xy;\n"
2259 "                       offset = float2(lerp(0.5, 1.5, dir.z < 0.0), 2.5);\n"
2260 "               }\n"
2261 "       }\n"
2262 "\n"
2263 "       float3 stc = float3(tc * ShadowMap_Parameters.x, ShadowMap_Parameters.w) / ma;\n"
2264 "       stc.xy += offset * ShadowMap_Parameters.y;\n"
2265 "       stc.z += ShadowMap_Parameters.z;\n"
2266 "       return stc;\n"
2267 "}\n"
2268 "# endif\n"
2269 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2270 "\n"
2271 "#ifdef USESHADOWMAPCUBE\n"
2272 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2273 "{\n"
2274 "    float3 adir = abs(dir);\n"
2275 "    return float4(dir, ShadowMap_Parameters.z + ShadowMap_Parameters.w / max(max(adir.x, adir.y), adir.z));\n"
2276 "}\n"
2277 "#endif\n"
2278 "\n"
2279 "# ifdef USESHADOWMAPRECT\n"
2280 "#ifdef USESHADOWMAPVSDCT\n"
2281 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2282 "#else\n"
2283 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2284 "#endif\n"
2285 "{\n"
2286 "#ifdef USESHADOWMAPVSDCT\n"
2287 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2288 "#else\n"
2289 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2290 "#endif\n"
2291 "       float f;\n"
2292 "#  ifdef USESHADOWSAMPLER\n"
2293 "\n"
2294 "#    ifdef USESHADOWMAPPCF\n"
2295 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2296 "    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"
2297 "#    else\n"
2298 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2299 "#    endif\n"
2300 "\n"
2301 "#  else\n"
2302 "\n"
2303 "#    ifdef USESHADOWMAPPCF\n"
2304 "#      if USESHADOWMAPPCF > 1\n"
2305 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2306 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2307 "    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"
2308 "    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"
2309 "    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"
2310 "    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"
2311 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2312 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2313 "#      else\n"
2314 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2315 "    float2 offset = frac(shadowmaptc.xy);\n"
2316 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2317 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2318 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2319 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2320 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2321 "#      endif\n"
2322 "#    else\n"
2323 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2324 "#    endif\n"
2325 "\n"
2326 "#  endif\n"
2327 "       return f;\n"
2328 "}\n"
2329 "# endif\n"
2330 "\n"
2331 "# ifdef USESHADOWMAP2D\n"
2332 "#ifdef USESHADOWMAPVSDCT\n"
2333 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2334 "#else\n"
2335 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2336 "#endif\n"
2337 "{\n"
2338 "#ifdef USESHADOWMAPVSDCT\n"
2339 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2340 "#else\n"
2341 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2342 "#endif\n"
2343 "    float f;\n"
2344 "\n"
2345 "#  ifdef USESHADOWSAMPLER\n"
2346 "#    ifdef USESHADOWMAPPCF\n"
2347 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2348 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2349 "    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"
2350 "#    else\n"
2351 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2352 "#    endif\n"
2353 "#  else\n"
2354 "#    ifdef USESHADOWMAPPCF\n"
2355 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2356 "#      ifdef GL_ARB_texture_gather\n"
2357 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2358 "#      else\n"
2359 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2360 "#      endif\n"
2361 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2362 "    center *= ShadowMap_TextureScale;\n"
2363 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2364 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2365 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2366 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2367 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2368 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2369 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2370 "#     else\n"
2371 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2372 "#      if USESHADOWMAPPCF > 1\n"
2373 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2374 "    center *= ShadowMap_TextureScale;\n"
2375 "    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"
2376 "    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"
2377 "    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"
2378 "    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"
2379 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2380 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2381 "#      else\n"
2382 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2383 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2384 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2385 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2386 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2387 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2388 "#      endif\n"
2389 "#     endif\n"
2390 "#    else\n"
2391 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2392 "#    endif\n"
2393 "#  endif\n"
2394 "    return f;\n"
2395 "}\n"
2396 "# endif\n"
2397 "\n"
2398 "# ifdef USESHADOWMAPCUBE\n"
2399 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2400 "{\n"
2401 "    // apply depth texture cubemap as light filter\n"
2402 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2403 "    float f;\n"
2404 "#  ifdef USESHADOWSAMPLER\n"
2405 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2406 "#  else\n"
2407 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2408 "#  endif\n"
2409 "    return f;\n"
2410 "}\n"
2411 "# endif\n"
2412 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2413 "#endif // FRAGMENT_SHADER\n"
2414 "\n"
2415 "\n"
2416 "\n"
2417 "\n"
2418 "#ifdef MODE_DEFERREDGEOMETRY\n"
2419 "#ifdef VERTEX_SHADER\n"
2420 "void main\n"
2421 "(\n"
2422 "float4 gl_Vertex : POSITION,\n"
2423 "uniform float4x4 ModelViewProjectionMatrix,\n"
2424 "#ifdef USEVERTEXTEXTUREBLEND\n"
2425 "float4 gl_Color : COLOR0,\n"
2426 "#endif\n"
2427 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2428 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2429 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2430 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2431 "uniform float4x4 TexMatrix,\n"
2432 "#ifdef USEVERTEXTEXTUREBLEND\n"
2433 "uniform float4x4 BackgroundTexMatrix,\n"
2434 "#endif\n"
2435 "uniform float4x4 ModelViewMatrix,\n"
2436 "#ifdef USEOFFSETMAPPING\n"
2437 "uniform float3 EyePosition,\n"
2438 "#endif\n"
2439 "out float4 gl_Position : POSITION,\n"
2440 "out float4 gl_FrontColor : COLOR,\n"
2441 "out float4 TexCoordBoth : TEXCOORD0,\n"
2442 "#ifdef USEOFFSETMAPPING\n"
2443 "out float3 EyeVector : TEXCOORD2,\n"
2444 "#endif\n"
2445 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2446 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2447 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2448 ")\n"
2449 "{\n"
2450 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2451 "#ifdef USEVERTEXTEXTUREBLEND\n"
2452 "       gl_FrontColor = gl_Color;\n"
2453 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2454 "#endif\n"
2455 "\n"
2456 "       // transform unnormalized eye direction into tangent space\n"
2457 "#ifdef USEOFFSETMAPPING\n"
2458 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2459 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2460 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2461 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2462 "#endif\n"
2463 "\n"
2464 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2465 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2466 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2467 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2468 "}\n"
2469 "#endif // VERTEX_SHADER\n"
2470 "\n"
2471 "#ifdef FRAGMENT_SHADER\n"
2472 "void main\n"
2473 "(\n"
2474 "float4 TexCoordBoth : TEXCOORD0,\n"
2475 "float3 EyeVector : TEXCOORD2,\n"
2476 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2477 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2478 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2479 "uniform sampler2D Texture_Normal,\n"
2480 "#ifdef USEALPHAKILL\n"
2481 "uniform sampler2D Texture_Color,\n"
2482 "#endif\n"
2483 "uniform sampler2D Texture_Gloss,\n"
2484 "#ifdef USEVERTEXTEXTUREBLEND\n"
2485 "uniform sampler2D Texture_SecondaryNormal,\n"
2486 "uniform sampler2D Texture_SecondaryGloss,\n"
2487 "#endif\n"
2488 "#ifdef USEOFFSETMAPPING\n"
2489 "uniform float OffsetMapping_Scale,\n"
2490 "#endif\n"
2491 "uniform half SpecularPower,\n"
2492 "out float4 gl_FragColor : COLOR\n"
2493 ")\n"
2494 "{\n"
2495 "       float2 TexCoord = TexCoordBoth.xy;\n"
2496 "#ifdef USEOFFSETMAPPING\n"
2497 "       // apply offsetmapping\n"
2498 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2499 "#define TexCoord TexCoordOffset\n"
2500 "#endif\n"
2501 "\n"
2502 "#ifdef USEALPHAKILL\n"
2503 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2504 "               discard;\n"
2505 "#endif\n"
2506 "\n"
2507 "#ifdef USEVERTEXTEXTUREBLEND\n"
2508 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2509 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2510 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2511 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2512 "#endif\n"
2513 "\n"
2514 "#ifdef USEVERTEXTEXTUREBLEND\n"
2515 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2516 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2517 "#else\n"
2518 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2519 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2520 "#endif\n"
2521 "\n"
2522 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2523 "}\n"
2524 "#endif // FRAGMENT_SHADER\n"
2525 "#else // !MODE_DEFERREDGEOMETRY\n"
2526 "\n"
2527 "\n"
2528 "\n"
2529 "\n"
2530 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2531 "#ifdef VERTEX_SHADER\n"
2532 "void main\n"
2533 "(\n"
2534 "float4 gl_Vertex : POSITION,\n"
2535 "uniform float4x4 ModelViewProjectionMatrix,\n"
2536 "uniform float4x4 ModelViewMatrix,\n"
2537 "out float4 gl_Position : POSITION,\n"
2538 "out float4 ModelViewPosition : TEXCOORD0\n"
2539 ")\n"
2540 "{\n"
2541 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2542 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2543 "}\n"
2544 "#endif // VERTEX_SHADER\n"
2545 "\n"
2546 "#ifdef FRAGMENT_SHADER\n"
2547 "void main\n"
2548 "(\n"
2549 "float2 Pixel : WPOS,\n"
2550 "float4 ModelViewPosition : TEXCOORD0,\n"
2551 "uniform float4x4 ViewToLight,\n"
2552 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2553 "uniform float3 LightPosition,\n"
2554 "uniform half2 PixelToScreenTexCoord,\n"
2555 "uniform half3 DeferredColor_Ambient,\n"
2556 "uniform half3 DeferredColor_Diffuse,\n"
2557 "#ifdef USESPECULAR\n"
2558 "uniform half3 DeferredColor_Specular,\n"
2559 "uniform half SpecularPower,\n"
2560 "#endif\n"
2561 "uniform sampler2D Texture_Attenuation,\n"
2562 "uniform sampler2D Texture_ScreenDepth,\n"
2563 "uniform sampler2D Texture_ScreenNormalMap,\n"
2564 "\n"
2565 "#ifdef USESHADOWMAPRECT\n"
2566 "# ifdef USESHADOWSAMPLER\n"
2567 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2568 "# else\n"
2569 "uniform samplerRECT Texture_ShadowMapRect,\n"
2570 "# endif\n"
2571 "#endif\n"
2572 "\n"
2573 "#ifdef USESHADOWMAP2D\n"
2574 "# ifdef USESHADOWSAMPLER\n"
2575 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2576 "# else\n"
2577 "uniform sampler2D Texture_ShadowMap2D,\n"
2578 "# endif\n"
2579 "#endif\n"
2580 "\n"
2581 "#ifdef USESHADOWMAPVSDCT\n"
2582 "uniform samplerCUBE Texture_CubeProjection,\n"
2583 "#endif\n"
2584 "\n"
2585 "#ifdef USESHADOWMAPCUBE\n"
2586 "# ifdef USESHADOWSAMPLER\n"
2587 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2588 "# else\n"
2589 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2590 "# endif\n"
2591 "#endif\n"
2592 "\n"
2593 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2594 "uniform float2 ShadowMap_TextureScale,\n"
2595 "uniform float4 ShadowMap_Parameters,\n"
2596 "#endif\n"
2597 "\n"
2598 "out float4 gl_FragData0 : COLOR0,\n"
2599 "out float4 gl_FragData1 : COLOR1\n"
2600 ")\n"
2601 "{\n"
2602 "       // calculate viewspace pixel position\n"
2603 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2604 "       ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2605 "       float3 position;\n"
2606 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2607 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2608 "       // decode viewspace pixel normal\n"
2609 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2610 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2611 "       // surfacenormal = pixel normal in viewspace\n"
2612 "       // LightVector = pixel to light in viewspace\n"
2613 "       // CubeVector = position in lightspace\n"
2614 "       // eyevector = pixel to view in viewspace\n"
2615 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2616 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2617 "#ifdef USEDIFFUSE\n"
2618 "       // calculate diffuse shading\n"
2619 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2620 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2621 "#endif\n"
2622 "#ifdef USESPECULAR\n"
2623 "       // calculate directional shading\n"
2624 "       float3 eyevector = position * -1.0;\n"
2625 "#  ifdef USEEXACTSPECULARMATH\n"
2626 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2627 "#  else\n"
2628 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2629 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2630 "#  endif\n"
2631 "#endif\n"
2632 "\n"
2633 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2634 "       fade *= ShadowMapCompare(CubeVector,\n"
2635 "# if defined(USESHADOWMAP2D)\n"
2636 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2637 "# endif\n"
2638 "# if defined(USESHADOWMAPRECT)\n"
2639 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2640 "# endif\n"
2641 "# if defined(USESHADOWMAPCUBE)\n"
2642 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2643 "# endif\n"
2644 "\n"
2645 "#ifdef USESHADOWMAPVSDCT\n"
2646 ", Texture_CubeProjection\n"
2647 "#endif\n"
2648 "       );\n"
2649 "#endif\n"
2650 "\n"
2651 "#ifdef USEDIFFUSE\n"
2652 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2653 "#else\n"
2654 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2655 "#endif\n"
2656 "#ifdef USESPECULAR\n"
2657 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2658 "#else\n"
2659 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2660 "#endif\n"
2661 "\n"
2662 "# ifdef USECUBEFILTER\n"
2663 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2664 "       gl_FragData0.rgb *= cubecolor;\n"
2665 "       gl_FragData1.rgb *= cubecolor;\n"
2666 "# endif\n"
2667 "}\n"
2668 "#endif // FRAGMENT_SHADER\n"
2669 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2670 "\n"
2671 "\n"
2672 "\n"
2673 "\n"
2674 "#ifdef VERTEX_SHADER\n"
2675 "void main\n"
2676 "(\n"
2677 "float4 gl_Vertex : POSITION,\n"
2678 "uniform float4x4 ModelViewProjectionMatrix,\n"
2679 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2680 "float4 gl_Color : COLOR0,\n"
2681 "#endif\n"
2682 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2683 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2684 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2685 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2686 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2687 "\n"
2688 "uniform float3 EyePosition,\n"
2689 "uniform float4x4 TexMatrix,\n"
2690 "#ifdef USEVERTEXTEXTUREBLEND\n"
2691 "uniform float4x4 BackgroundTexMatrix,\n"
2692 "#endif\n"
2693 "#ifdef MODE_LIGHTSOURCE\n"
2694 "uniform float4x4 ModelToLight,\n"
2695 "#endif\n"
2696 "#ifdef MODE_LIGHTSOURCE\n"
2697 "uniform float3 LightPosition,\n"
2698 "#endif\n"
2699 "#ifdef MODE_LIGHTDIRECTION\n"
2700 "uniform float3 LightDir,\n"
2701 "#endif\n"
2702 "uniform float4 FogPlane,\n"
2703 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2704 "uniform float3 LightPosition,\n"
2705 "#endif\n"
2706 "\n"
2707 "out float4 gl_FrontColor : COLOR,\n"
2708 "out float4 TexCoordBoth : TEXCOORD0,\n"
2709 "#ifdef USELIGHTMAP\n"
2710 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2711 "#endif\n"
2712 "#ifdef USEEYEVECTOR\n"
2713 "out float3 EyeVector : TEXCOORD2,\n"
2714 "#endif\n"
2715 "#ifdef USEREFLECTION\n"
2716 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2717 "#endif\n"
2718 "#ifdef USEFOG\n"
2719 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2720 "#endif\n"
2721 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2722 "out float3 LightVector : TEXCOORD5,\n"
2723 "#endif\n"
2724 "#ifdef MODE_LIGHTSOURCE\n"
2725 "out float3 CubeVector : TEXCOORD3,\n"
2726 "#endif\n"
2727 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2728 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2729 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2730 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2731 "#endif\n"
2732 "out float4 gl_Position : POSITION\n"
2733 ")\n"
2734 "{\n"
2735 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2736 "       gl_FrontColor = gl_Color;\n"
2737 "#endif\n"
2738 "       // copy the surface texcoord\n"
2739 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2740 "#ifdef USEVERTEXTEXTUREBLEND\n"
2741 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2742 "#endif\n"
2743 "#ifdef USELIGHTMAP\n"
2744 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2745 "#endif\n"
2746 "\n"
2747 "#ifdef MODE_LIGHTSOURCE\n"
2748 "       // transform vertex position into light attenuation/cubemap space\n"
2749 "       // (-1 to +1 across the light box)\n"
2750 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2751 "\n"
2752 "# ifdef USEDIFFUSE\n"
2753 "       // transform unnormalized light direction into tangent space\n"
2754 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2755 "       //  normalize it per pixel)\n"
2756 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2757 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2758 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2759 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2760 "# endif\n"
2761 "#endif\n"
2762 "\n"
2763 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2764 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2765 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2766 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2767 "#endif\n"
2768 "\n"
2769 "       // transform unnormalized eye direction into tangent space\n"
2770 "#ifdef USEEYEVECTOR\n"
2771 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2772 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2773 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2774 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2775 "#endif\n"
2776 "\n"
2777 "#ifdef USEFOG\n"
2778 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2779 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2780 "#endif\n"
2781 "\n"
2782 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2783 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2784 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2785 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2786 "#endif\n"
2787 "\n"
2788 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2789 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2790 "\n"
2791 "#ifdef USEREFLECTION\n"
2792 "       ModelViewProjectionPosition = gl_Position;\n"
2793 "#endif\n"
2794 "}\n"
2795 "#endif // VERTEX_SHADER\n"
2796 "\n"
2797 "\n"
2798 "\n"
2799 "\n"
2800 "#ifdef FRAGMENT_SHADER\n"
2801 "void main\n"
2802 "(\n"
2803 "#ifdef USEDEFERREDLIGHTMAP\n"
2804 "float2 Pixel : WPOS,\n"
2805 "#endif\n"
2806 "float4 gl_FrontColor : COLOR,\n"
2807 "float4 TexCoordBoth : TEXCOORD0,\n"
2808 "#ifdef USELIGHTMAP\n"
2809 "float2 TexCoordLightmap : TEXCOORD1,\n"
2810 "#endif\n"
2811 "#ifdef USEEYEVECTOR\n"
2812 "float3 EyeVector : TEXCOORD2,\n"
2813 "#endif\n"
2814 "#ifdef USEREFLECTION\n"
2815 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2816 "#endif\n"
2817 "#ifdef USEFOG\n"
2818 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2819 "#endif\n"
2820 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2821 "float3 LightVector : TEXCOORD5,\n"
2822 "#endif\n"
2823 "#ifdef MODE_LIGHTSOURCE\n"
2824 "float3 CubeVector : TEXCOORD3,\n"
2825 "#endif\n"
2826 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2827 "float4 ModelViewPosition : TEXCOORD0,\n"
2828 "#endif\n"
2829 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2830 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2831 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2832 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2833 "#endif\n"
2834 "\n"
2835 "uniform sampler2D Texture_Normal,\n"
2836 "uniform sampler2D Texture_Color,\n"
2837 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2838 "uniform sampler2D Texture_Gloss,\n"
2839 "#endif\n"
2840 "#ifdef USEGLOW\n"
2841 "uniform sampler2D Texture_Glow,\n"
2842 "#endif\n"
2843 "#ifdef USEVERTEXTEXTUREBLEND\n"
2844 "uniform sampler2D Texture_SecondaryNormal,\n"
2845 "uniform sampler2D Texture_SecondaryColor,\n"
2846 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2847 "uniform sampler2D Texture_SecondaryGloss,\n"
2848 "#endif\n"
2849 "#ifdef USEGLOW\n"
2850 "uniform sampler2D Texture_SecondaryGlow,\n"
2851 "#endif\n"
2852 "#endif\n"
2853 "#ifdef USECOLORMAPPING\n"
2854 "uniform sampler2D Texture_Pants,\n"
2855 "uniform sampler2D Texture_Shirt,\n"
2856 "#endif\n"
2857 "#ifdef USEFOG\n"
2858 "uniform sampler2D Texture_FogMask,\n"
2859 "#endif\n"
2860 "#ifdef USELIGHTMAP\n"
2861 "uniform sampler2D Texture_Lightmap,\n"
2862 "#endif\n"
2863 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2864 "uniform sampler2D Texture_Deluxemap,\n"
2865 "#endif\n"
2866 "#ifdef USEREFLECTION\n"
2867 "uniform sampler2D Texture_Reflection,\n"
2868 "#endif\n"
2869 "\n"
2870 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2871 "uniform sampler2D Texture_ScreenDepth,\n"
2872 "uniform sampler2D Texture_ScreenNormalMap,\n"
2873 "#endif\n"
2874 "#ifdef USEDEFERREDLIGHTMAP\n"
2875 "uniform sampler2D Texture_ScreenDiffuse,\n"
2876 "uniform sampler2D Texture_ScreenSpecular,\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USECOLORMAPPING\n"
2880 "uniform half3 Color_Pants,\n"
2881 "uniform half3 Color_Shirt,\n"
2882 "#endif\n"
2883 "#ifdef USEFOG\n"
2884 "uniform float3 FogColor,\n"
2885 "uniform float FogRangeRecip,\n"
2886 "uniform float FogPlaneViewDist,\n"
2887 "uniform float FogHeightFade,\n"
2888 "#endif\n"
2889 "\n"
2890 "#ifdef USEOFFSETMAPPING\n"
2891 "uniform float OffsetMapping_Scale,\n"
2892 "#endif\n"
2893 "\n"
2894 "#ifdef USEDEFERREDLIGHTMAP\n"
2895 "uniform half2 PixelToScreenTexCoord,\n"
2896 "uniform half3 DeferredMod_Diffuse,\n"
2897 "uniform half3 DeferredMod_Specular,\n"
2898 "#endif\n"
2899 "uniform half3 Color_Ambient,\n"
2900 "uniform half3 Color_Diffuse,\n"
2901 "uniform half3 Color_Specular,\n"
2902 "uniform half SpecularPower,\n"
2903 "#ifdef USEGLOW\n"
2904 "uniform half3 Color_Glow,\n"
2905 "#endif\n"
2906 "uniform half Alpha,\n"
2907 "#ifdef USEREFLECTION\n"
2908 "uniform float4 DistortScaleRefractReflect,\n"
2909 "uniform float4 ScreenScaleRefractReflect,\n"
2910 "uniform float4 ScreenCenterRefractReflect,\n"
2911 "uniform half4 ReflectColor,\n"
2912 "#endif\n"
2913 "#ifdef USEREFLECTCUBE\n"
2914 "uniform float4x4 ModelToReflectCube,\n"
2915 "uniform sampler2D Texture_ReflectMask,\n"
2916 "uniform samplerCUBE Texture_ReflectCube,\n"
2917 "#endif\n"
2918 "#ifdef MODE_LIGHTDIRECTION\n"
2919 "uniform half3 LightColor,\n"
2920 "#endif\n"
2921 "#ifdef MODE_LIGHTSOURCE\n"
2922 "uniform half3 LightColor,\n"
2923 "#endif\n"
2924 "\n"
2925 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2926 "uniform sampler2D Texture_Attenuation,\n"
2927 "uniform samplerCUBE Texture_Cube,\n"
2928 "\n"
2929 "#ifdef USESHADOWMAPRECT\n"
2930 "# ifdef USESHADOWSAMPLER\n"
2931 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2932 "# else\n"
2933 "uniform samplerRECT Texture_ShadowMapRect,\n"
2934 "# endif\n"
2935 "#endif\n"
2936 "\n"
2937 "#ifdef USESHADOWMAP2D\n"
2938 "# ifdef USESHADOWSAMPLER\n"
2939 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2940 "# else\n"
2941 "uniform sampler2D Texture_ShadowMap2D,\n"
2942 "# endif\n"
2943 "#endif\n"
2944 "\n"
2945 "#ifdef USESHADOWMAPVSDCT\n"
2946 "uniform samplerCUBE Texture_CubeProjection,\n"
2947 "#endif\n"
2948 "\n"
2949 "#ifdef USESHADOWMAPCUBE\n"
2950 "# ifdef USESHADOWSAMPLER\n"
2951 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2952 "# else\n"
2953 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2954 "# endif\n"
2955 "#endif\n"
2956 "\n"
2957 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2958 "uniform float2 ShadowMap_TextureScale,\n"
2959 "uniform float4 ShadowMap_Parameters,\n"
2960 "#endif\n"
2961 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2962 "\n"
2963 "out float4 gl_FragColor : COLOR\n"
2964 ")\n"
2965 "{\n"
2966 "       float2 TexCoord = TexCoordBoth.xy;\n"
2967 "#ifdef USEVERTEXTEXTUREBLEND\n"
2968 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2969 "#endif\n"
2970 "#ifdef USEOFFSETMAPPING\n"
2971 "       // apply offsetmapping\n"
2972 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2973 "#define TexCoord TexCoordOffset\n"
2974 "#endif\n"
2975 "\n"
2976 "       // combine the diffuse textures (base, pants, shirt)\n"
2977 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2978 "#ifdef USEALPHAKILL\n"
2979 "       if (color.a < 0.5)\n"
2980 "               discard;\n"
2981 "#endif\n"
2982 "       color.a *= Alpha;\n"
2983 "#ifdef USECOLORMAPPING\n"
2984 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
2985 "#endif\n"
2986 "#ifdef USEVERTEXTEXTUREBLEND\n"
2987 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
2988 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
2989 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
2990 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
2991 "       color.a = 1.0;\n"
2992 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
2993 "#endif\n"
2994 "\n"
2995 "       // get the surface normal\n"
2996 "#ifdef USEVERTEXTEXTUREBLEND\n"
2997 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
2998 "#else\n"
2999 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3000 "#endif\n"
3001 "\n"
3002 "       // get the material colors\n"
3003 "       half3 diffusetex = color.rgb;\n"
3004 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3005 "# ifdef USEVERTEXTEXTUREBLEND\n"
3006 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3007 "# else\n"
3008 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3009 "# endif\n"
3010 "#endif\n"
3011 "\n"
3012 "#ifdef USEREFLECTCUBE\n"
3013 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3014 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3015 "       vec3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3016 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3017 "#endif\n"
3018 "\n"
3019 "\n"
3020 "\n"
3021 "\n"
3022 "#ifdef MODE_LIGHTSOURCE\n"
3023 "       // light source\n"
3024 "#ifdef USEDIFFUSE\n"
3025 "       half3 lightnormal = half3(normalize(LightVector));\n"
3026 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3027 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3028 "#ifdef USESPECULAR\n"
3029 "#ifdef USEEXACTSPECULARMATH\n"
3030 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3031 "#else\n"
3032 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3033 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3034 "#endif\n"
3035 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3036 "#endif\n"
3037 "#else\n"
3038 "       color.rgb = diffusetex * Color_Ambient;\n"
3039 "#endif\n"
3040 "       color.rgb *= LightColor;\n"
3041 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3042 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3043 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3044 "# if defined(USESHADOWMAP2D)\n"
3045 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3046 "# endif\n"
3047 "# if defined(USESHADOWMAPRECT)\n"
3048 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3049 "# endif\n"
3050 "# if defined(USESHADOWMAPCUBE)\n"
3051 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3052 "# endif\n"
3053 "\n"
3054 "#ifdef USESHADOWMAPVSDCT\n"
3055 ", Texture_CubeProjection\n"
3056 "#endif\n"
3057 "       );\n"
3058 "\n"
3059 "#endif\n"
3060 "# ifdef USECUBEFILTER\n"
3061 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3062 "# endif\n"
3063 "#endif // MODE_LIGHTSOURCE\n"
3064 "\n"
3065 "\n"
3066 "\n"
3067 "\n"
3068 "#ifdef MODE_LIGHTDIRECTION\n"
3069 "#define SHADING\n"
3070 "#ifdef USEDIFFUSE\n"
3071 "       half3 lightnormal = half3(normalize(LightVector));\n"
3072 "#endif\n"
3073 "#define lightcolor LightColor\n"
3074 "#endif // MODE_LIGHTDIRECTION\n"
3075 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3076 "#define SHADING\n"
3077 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3078 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3079 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3080 "       // convert modelspace light vector to tangentspace\n"
3081 "       half3 lightnormal;\n"
3082 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3083 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3084 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3085 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3086 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3087 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3088 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3089 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3090 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3091 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3092 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3093 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3094 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3095 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3096 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3097 "#define SHADING\n"
3098 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3099 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3100 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3101 "#endif\n"
3102 "\n"
3103 "\n"
3104 "\n"
3105 "\n"
3106 "#ifdef MODE_LIGHTMAP\n"
3107 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3108 "#endif // MODE_LIGHTMAP\n"
3109 "#ifdef MODE_VERTEXCOLOR\n"
3110 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3111 "#endif // MODE_VERTEXCOLOR\n"
3112 "#ifdef MODE_FLATCOLOR\n"
3113 "       color.rgb = diffusetex * Color_Ambient;\n"
3114 "#endif // MODE_FLATCOLOR\n"
3115 "\n"
3116 "\n"
3117 "\n"
3118 "\n"
3119 "#ifdef SHADING\n"
3120 "# ifdef USEDIFFUSE\n"
3121 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3122 "#  ifdef USESPECULAR\n"
3123 "#   ifdef USEEXACTSPECULARMATH\n"
3124 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3125 "#   else\n"
3126 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3127 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3128 "#   endif\n"
3129 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3130 "#  else\n"
3131 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3132 "#  endif\n"
3133 "# else\n"
3134 "       color.rgb = diffusetex * Color_Ambient;\n"
3135 "# endif\n"
3136 "#endif\n"
3137 "\n"
3138 "#ifdef USEDEFERREDLIGHTMAP\n"
3139 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3140 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3141 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3142 "#endif\n"
3143 "\n"
3144 "#ifdef USEGLOW\n"
3145 "#ifdef USEVERTEXTEXTUREBLEND\n"
3146 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3147 "#else\n"
3148 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3149 "#endif\n"
3150 "#endif\n"
3151 "\n"
3152 "#ifdef USEFOG\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "       color.rgb *= half(FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3155 "#else\n"
3156 "       color.rgb = lerp(FogColor, float3(color.rgb), FogVertex(EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask));\n"
3157 "#endif\n"
3158 "#endif\n"
3159 "\n"
3160 "       // 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"
3161 "#ifdef USEREFLECTION\n"
3162 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3163 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3164 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3165 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3166 "       // FIXME temporary hack to detect the case that the reflection\n"
3167 "       // gets blackened at edges due to leaving the area that contains actual\n"
3168 "       // content.\n"
3169 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3170 "       // 'appening.\n"
3171 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3172 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3173 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3174 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3175 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3176 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3177 "#endif\n"
3178 "\n"
3179 "       gl_FragColor = float4(color);\n"
3180 "}\n"
3181 "#endif // FRAGMENT_SHADER\n"
3182 "\n"
3183 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3184 "#endif // !MODE_DEFERREDGEOMETRY\n"
3185 "#endif // !MODE_WATER\n"
3186 "#endif // !MODE_REFRACTION\n"
3187 "#endif // !MODE_BLOOMBLUR\n"
3188 "#endif // !MODE_GENERIC\n"
3189 "#endif // !MODE_POSTPROCESS\n"
3190 "#endif // !MODE_SHOWDEPTH\n"
3191 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3192 ;
3193
3194 char *glslshaderstring = NULL;
3195 char *cgshaderstring = NULL;
3196
3197 //=======================================================================================================================================================
3198
3199 typedef struct shaderpermutationinfo_s
3200 {
3201         const char *pretext;
3202         const char *name;
3203 }
3204 shaderpermutationinfo_t;
3205
3206 typedef struct shadermodeinfo_s
3207 {
3208         const char *vertexfilename;
3209         const char *geometryfilename;
3210         const char *fragmentfilename;
3211         const char *pretext;
3212         const char *name;
3213 }
3214 shadermodeinfo_t;
3215
3216 typedef enum shaderpermutation_e
3217 {
3218         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3219         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3220         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3221         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3222         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3223         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3224         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3225         SHADERPERMUTATION_GAMMARAMPS = 1<<7, ///< gamma (postprocessing only)
3226         SHADERPERMUTATION_CUBEFILTER = 1<<8, ///< (lightsource) use cubemap light filter
3227         SHADERPERMUTATION_GLOW = 1<<9, ///< (lightmap) blend in an additive glow texture
3228         SHADERPERMUTATION_BLOOM = 1<<10, ///< bloom (postprocessing only)
3229         SHADERPERMUTATION_SPECULAR = 1<<11, ///< (lightsource or deluxemapping) render specular effects
3230         SHADERPERMUTATION_POSTPROCESSING = 1<<12, ///< user defined postprocessing (postprocessing only)
3231         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<13, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3232         SHADERPERMUTATION_REFLECTION = 1<<14, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3233         SHADERPERMUTATION_OFFSETMAPPING = 1<<15, ///< adjust texcoords to roughly simulate a displacement mapped surface
3234         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<16, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3235         SHADERPERMUTATION_SHADOWMAPRECT = 1<<17, ///< (lightsource) use shadowmap rectangle texture as light filter
3236         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<18, ///< (lightsource) use shadowmap cubemap texture as light filter
3237         SHADERPERMUTATION_SHADOWMAP2D = 1<<19, ///< (lightsource) use shadowmap rectangle texture as light filter
3238         SHADERPERMUTATION_SHADOWMAPPCF = 1<<20, ///< (lightsource) use percentage closer filtering on shadowmap test results
3239         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<21, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3240         SHADERPERMUTATION_SHADOWSAMPLER = 1<<22, ///< (lightsource) use hardware shadowmap test
3241         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<23, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3242         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<24, //< (lightsource) use orthographic shadowmap projection
3243         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<25, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3244         SHADERPERMUTATION_ALPHAKILL = 1<<26, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3245         SHADERPERMUTATION_REFLECTCUBE = 1<<27, ///< fake reflections using global cubemap (not HDRI light probe)
3246         SHADERPERMUTATION_LIMIT = 1<<28, ///< size of permutations array
3247         SHADERPERMUTATION_COUNT = 28 ///< size of shaderpermutationinfo array
3248 }
3249 shaderpermutation_t;
3250
3251 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3252 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3253 {
3254         {"#define USEDIFFUSE\n", " diffuse"},
3255         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3256         {"#define USEVIEWTINT\n", " viewtint"},
3257         {"#define USECOLORMAPPING\n", " colormapping"},
3258         {"#define USESATURATION\n", " saturation"},
3259         {"#define USEFOGINSIDE\n", " foginside"},
3260         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3261         {"#define USEGAMMARAMPS\n", " gammaramps"},
3262         {"#define USECUBEFILTER\n", " cubefilter"},
3263         {"#define USEGLOW\n", " glow"},
3264         {"#define USEBLOOM\n", " bloom"},
3265         {"#define USESPECULAR\n", " specular"},
3266         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3267         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3268         {"#define USEREFLECTION\n", " reflection"},
3269         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3270         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3271         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3272         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3273         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3274         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3275         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3276         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3277         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3278         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3279         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3280         {"#define USEALPHAKILL\n", " alphakill"},
3281         {"#define USEREFLECTCUBE\n", " reflectcube"},
3282 };
3283
3284 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3285 typedef enum shadermode_e
3286 {
3287         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3288         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3289         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3290         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3291         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3292         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3293         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3294         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3295         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3296         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3297         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3298         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3299         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3300         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3301         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3302         SHADERMODE_COUNT
3303 }
3304 shadermode_t;
3305
3306 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3307 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3308 {
3309         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3310         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3311         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3312         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3313         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3314         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3315         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3316         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3317         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3318         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3319         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3320         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3321         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3322         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3323         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3324 };
3325
3326 #ifdef SUPPORTCG
3327 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3328 {
3329         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3330         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3331         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3332         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3333         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3334         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3335         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3336         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3337         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3338         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3339         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3340         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3341         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3342         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3343         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3344 };
3345 #endif
3346
3347 struct r_glsl_permutation_s;
3348 typedef struct r_glsl_permutation_s
3349 {
3350         /// hash lookup data
3351         struct r_glsl_permutation_s *hashnext;
3352         unsigned int mode;
3353         unsigned int permutation;
3354
3355         /// indicates if we have tried compiling this permutation already
3356         qboolean compiled;
3357         /// 0 if compilation failed
3358         int program;
3359         /// locations of detected uniforms in program object, or -1 if not found
3360         int loc_Texture_First;
3361         int loc_Texture_Second;
3362         int loc_Texture_GammaRamps;
3363         int loc_Texture_Normal;
3364         int loc_Texture_Color;
3365         int loc_Texture_Gloss;
3366         int loc_Texture_Glow;
3367         int loc_Texture_SecondaryNormal;
3368         int loc_Texture_SecondaryColor;
3369         int loc_Texture_SecondaryGloss;
3370         int loc_Texture_SecondaryGlow;
3371         int loc_Texture_Pants;
3372         int loc_Texture_Shirt;
3373         int loc_Texture_FogMask;
3374         int loc_Texture_Lightmap;
3375         int loc_Texture_Deluxemap;
3376         int loc_Texture_Attenuation;
3377         int loc_Texture_Cube;
3378         int loc_Texture_Refraction;
3379         int loc_Texture_Reflection;
3380         int loc_Texture_ShadowMapRect;
3381         int loc_Texture_ShadowMapCube;
3382         int loc_Texture_ShadowMap2D;
3383         int loc_Texture_CubeProjection;
3384         int loc_Texture_ScreenDepth;
3385         int loc_Texture_ScreenNormalMap;
3386         int loc_Texture_ScreenDiffuse;
3387         int loc_Texture_ScreenSpecular;
3388         int loc_Texture_ReflectMask;
3389         int loc_Texture_ReflectCube;
3390         int loc_Alpha;
3391         int loc_BloomBlur_Parameters;
3392         int loc_ClientTime;
3393         int loc_Color_Ambient;
3394         int loc_Color_Diffuse;
3395         int loc_Color_Specular;
3396         int loc_Color_Glow;
3397         int loc_Color_Pants;
3398         int loc_Color_Shirt;
3399         int loc_DeferredColor_Ambient;
3400         int loc_DeferredColor_Diffuse;
3401         int loc_DeferredColor_Specular;
3402         int loc_DeferredMod_Diffuse;
3403         int loc_DeferredMod_Specular;
3404         int loc_DistortScaleRefractReflect;
3405         int loc_EyePosition;
3406         int loc_FogColor;
3407         int loc_FogHeightFade;
3408         int loc_FogPlane;
3409         int loc_FogPlaneViewDist;
3410         int loc_FogRangeRecip;
3411         int loc_LightColor;
3412         int loc_LightDir;
3413         int loc_LightPosition;
3414         int loc_OffsetMapping_Scale;
3415         int loc_PixelSize;
3416         int loc_ReflectColor;
3417         int loc_ReflectFactor;
3418         int loc_ReflectOffset;
3419         int loc_RefractColor;
3420         int loc_Saturation;
3421         int loc_ScreenCenterRefractReflect;
3422         int loc_ScreenScaleRefractReflect;
3423         int loc_ScreenToDepth;
3424         int loc_ShadowMap_Parameters;
3425         int loc_ShadowMap_TextureScale;
3426         int loc_SpecularPower;
3427         int loc_UserVec1;
3428         int loc_UserVec2;
3429         int loc_UserVec3;
3430         int loc_UserVec4;
3431         int loc_ViewTintColor;
3432         int loc_ViewToLight;
3433         int loc_ModelToLight;
3434         int loc_TexMatrix;
3435         int loc_BackgroundTexMatrix;
3436         int loc_ModelViewProjectionMatrix;
3437         int loc_ModelViewMatrix;
3438         int loc_PixelToScreenTexCoord;
3439         int loc_ModelToReflectCube;
3440         int loc_ShadowMapMatrix;        
3441 }
3442 r_glsl_permutation_t;
3443
3444 #define SHADERPERMUTATION_HASHSIZE 256
3445
3446 /// information about each possible shader permutation
3447 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3448 /// currently selected permutation
3449 r_glsl_permutation_t *r_glsl_permutation;
3450 /// storage for permutations linked in the hash table
3451 memexpandablearray_t r_glsl_permutationarray;
3452
3453 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3454 {
3455         //unsigned int hashdepth = 0;
3456         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3457         r_glsl_permutation_t *p;
3458         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3459         {
3460                 if (p->mode == mode && p->permutation == permutation)
3461                 {
3462                         //if (hashdepth > 10)
3463                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3464                         return p;
3465                 }
3466                 //hashdepth++;
3467         }
3468         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3469         p->mode = mode;
3470         p->permutation = permutation;
3471         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3472         r_glsl_permutationhash[mode][hashindex] = p;
3473         //if (hashdepth > 10)
3474         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3475         return p;
3476 }
3477
3478 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3479 {
3480         char *shaderstring;
3481         if (!filename || !filename[0])
3482                 return NULL;
3483         if (!strcmp(filename, "glsl/default.glsl"))
3484         {
3485                 if (!glslshaderstring)
3486                 {
3487                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3488                         if (glslshaderstring)
3489                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3490                         else
3491                                 glslshaderstring = (char *)builtinshaderstring;
3492                 }
3493                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3494                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3495                 return shaderstring;
3496         }
3497         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3498         if (shaderstring)
3499         {
3500                 if (printfromdisknotice)
3501                         Con_DPrintf("from disk %s... ", filename);
3502                 return shaderstring;
3503         }
3504         return shaderstring;
3505 }
3506
3507 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3508 {
3509         int i;
3510         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3511         int vertstrings_count = 0;
3512         int geomstrings_count = 0;
3513         int fragstrings_count = 0;
3514         char *vertexstring, *geometrystring, *fragmentstring;
3515         const char *vertstrings_list[32+3];
3516         const char *geomstrings_list[32+3];
3517         const char *fragstrings_list[32+3];
3518         char permutationname[256];
3519
3520         if (p->compiled)
3521                 return;
3522         p->compiled = true;
3523         p->program = 0;
3524
3525         permutationname[0] = 0;
3526         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3527         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3528         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3529
3530         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3531
3532         // the first pretext is which type of shader to compile as
3533         // (later these will all be bound together as a program object)
3534         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3535         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3536         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3537
3538         // the second pretext is the mode (for example a light source)
3539         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3540         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3541         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3542         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3543
3544         // now add all the permutation pretexts
3545         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3546         {
3547                 if (permutation & (1<<i))
3548                 {
3549                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3550                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3551                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3552                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3553                 }
3554                 else
3555                 {
3556                         // keep line numbers correct
3557                         vertstrings_list[vertstrings_count++] = "\n";
3558                         geomstrings_list[geomstrings_count++] = "\n";
3559                         fragstrings_list[fragstrings_count++] = "\n";
3560                 }
3561         }
3562
3563         // now append the shader text itself
3564         vertstrings_list[vertstrings_count++] = vertexstring;
3565         geomstrings_list[geomstrings_count++] = geometrystring;
3566         fragstrings_list[fragstrings_count++] = fragmentstring;
3567
3568         // if any sources were NULL, clear the respective list
3569         if (!vertexstring)
3570                 vertstrings_count = 0;
3571         if (!geometrystring)
3572                 geomstrings_count = 0;
3573         if (!fragmentstring)
3574                 fragstrings_count = 0;
3575
3576         // compile the shader program
3577         if (vertstrings_count + geomstrings_count + fragstrings_count)
3578                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3579         if (p->program)
3580         {
3581                 CHECKGLERROR
3582                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3583                 // look up all the uniform variable names we care about, so we don't
3584                 // have to look them up every time we set them
3585
3586                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3587                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3588                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3589                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3590                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3591                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3592                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3593                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3594                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3595                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3596                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3597                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3598                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3599                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3600                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3601                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3602                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3603                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3604                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3605                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3606                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3607                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3608                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3609                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3610                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3611                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3612                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3613                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3614                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3615                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3616                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3617                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3618                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3619                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3620                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3621                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3622                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3623                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3624                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3625                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3626                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3627                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3628                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3629                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3630                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3631                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3632                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3633                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3634                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3635                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3636                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3637                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3638                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3639                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3640                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3641                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3642                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3643                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3644                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3645                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3646                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3647                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3648                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3649                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3650                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3651                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3652                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3653                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3654                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3655                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3656                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3657                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3658                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3659                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3660                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3661                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3662                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3663                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3664                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3665                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3666                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3667                 // initialize the samplers to refer to the texture units we use
3668                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3669                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3670                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3671                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3672                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3673                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3674                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3675                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3676                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3677                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3678                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3679                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3680                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3681                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3682                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3683                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3684                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3685                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3686                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3687                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3688                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , GL20TU_SHADOWMAPRECT);
3689                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3690                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3691                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3692                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3693                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3694                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3695                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3696                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3697                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3698                 CHECKGLERROR
3699                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3700         }
3701         else
3702                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3703
3704         // free the strings
3705         if (vertexstring)
3706                 Mem_Free(vertexstring);
3707         if (geometrystring)
3708                 Mem_Free(geometrystring);
3709         if (fragmentstring)
3710                 Mem_Free(fragmentstring);
3711 }
3712
3713 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3714 {
3715         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3716         if (r_glsl_permutation != perm)
3717         {
3718                 r_glsl_permutation = perm;
3719                 if (!r_glsl_permutation->program)
3720                 {
3721                         if (!r_glsl_permutation->compiled)
3722                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3723                         if (!r_glsl_permutation->program)
3724                         {
3725                                 // remove features until we find a valid permutation
3726                                 int i;
3727                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3728                                 {
3729                                         // reduce i more quickly whenever it would not remove any bits
3730                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3731                                         if (!(permutation & j))
3732                                                 continue;
3733                                         permutation -= j;
3734                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3735                                         if (!r_glsl_permutation->compiled)
3736                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3737                                         if (r_glsl_permutation->program)
3738                                                 break;
3739                                 }
3740                                 if (i >= SHADERPERMUTATION_COUNT)
3741                                 {
3742                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3743                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3744                                         qglUseProgramObjectARB(0);CHECKGLERROR
3745                                         return; // no bit left to clear, entire mode is broken
3746                                 }
3747                         }
3748                 }
3749                 CHECKGLERROR
3750                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3751         }
3752         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3753         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3754         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3755 }
3756
3757 #ifdef SUPPORTCG
3758 #include <Cg/cgGL.h>
3759 struct r_cg_permutation_s;
3760 typedef struct r_cg_permutation_s
3761 {
3762         /// hash lookup data
3763         struct r_cg_permutation_s *hashnext;
3764         unsigned int mode;
3765         unsigned int permutation;
3766
3767         /// indicates if we have tried compiling this permutation already
3768         qboolean compiled;
3769         /// 0 if compilation failed
3770         CGprogram vprogram;
3771         CGprogram fprogram;
3772         /// locations of detected parameters in programs, or NULL if not found
3773         CGparameter vp_EyePosition;
3774         CGparameter vp_FogPlane;
3775         CGparameter vp_LightDir;
3776         CGparameter vp_LightPosition;
3777         CGparameter vp_ModelToLight;
3778         CGparameter vp_TexMatrix;
3779         CGparameter vp_BackgroundTexMatrix;
3780         CGparameter vp_ModelViewProjectionMatrix;
3781         CGparameter vp_ModelViewMatrix;
3782         CGparameter vp_ShadowMapMatrix;
3783
3784         CGparameter fp_Texture_First;
3785         CGparameter fp_Texture_Second;
3786         CGparameter fp_Texture_GammaRamps;
3787         CGparameter fp_Texture_Normal;
3788         CGparameter fp_Texture_Color;
3789         CGparameter fp_Texture_Gloss;
3790         CGparameter fp_Texture_Glow;
3791         CGparameter fp_Texture_SecondaryNormal;
3792         CGparameter fp_Texture_SecondaryColor;
3793         CGparameter fp_Texture_SecondaryGloss;
3794         CGparameter fp_Texture_SecondaryGlow;
3795         CGparameter fp_Texture_Pants;
3796         CGparameter fp_Texture_Shirt;
3797         CGparameter fp_Texture_FogMask;
3798         CGparameter fp_Texture_Lightmap;
3799         CGparameter fp_Texture_Deluxemap;
3800         CGparameter fp_Texture_Attenuation;
3801         CGparameter fp_Texture_Cube;
3802         CGparameter fp_Texture_Refraction;
3803         CGparameter fp_Texture_Reflection;
3804         CGparameter fp_Texture_ShadowMapRect;
3805         CGparameter fp_Texture_ShadowMapCube;
3806         CGparameter fp_Texture_ShadowMap2D;
3807         CGparameter fp_Texture_CubeProjection;
3808         CGparameter fp_Texture_ScreenDepth;
3809         CGparameter fp_Texture_ScreenNormalMap;
3810         CGparameter fp_Texture_ScreenDiffuse;
3811         CGparameter fp_Texture_ScreenSpecular;
3812         CGparameter fp_Texture_ReflectMask;
3813         CGparameter fp_Texture_ReflectCube;
3814         CGparameter fp_Alpha;
3815         CGparameter fp_BloomBlur_Parameters;
3816         CGparameter fp_ClientTime;
3817         CGparameter fp_Color_Ambient;
3818         CGparameter fp_Color_Diffuse;
3819         CGparameter fp_Color_Specular;
3820         CGparameter fp_Color_Glow;
3821         CGparameter fp_Color_Pants;
3822         CGparameter fp_Color_Shirt;
3823         CGparameter fp_DeferredColor_Ambient;
3824         CGparameter fp_DeferredColor_Diffuse;
3825         CGparameter fp_DeferredColor_Specular;
3826         CGparameter fp_DeferredMod_Diffuse;
3827         CGparameter fp_DeferredMod_Specular;
3828         CGparameter fp_DistortScaleRefractReflect;
3829         CGparameter fp_EyePosition;
3830         CGparameter fp_FogColor;
3831         CGparameter fp_FogHeightFade;
3832         CGparameter fp_FogPlane;
3833         CGparameter fp_FogPlaneViewDist;
3834         CGparameter fp_FogRangeRecip;
3835         CGparameter fp_LightColor;
3836         CGparameter fp_LightDir;
3837         CGparameter fp_LightPosition;
3838         CGparameter fp_OffsetMapping_Scale;
3839         CGparameter fp_PixelSize;
3840         CGparameter fp_ReflectColor;
3841         CGparameter fp_ReflectFactor;
3842         CGparameter fp_ReflectOffset;
3843         CGparameter fp_RefractColor;
3844         CGparameter fp_Saturation;
3845         CGparameter fp_ScreenCenterRefractReflect;
3846         CGparameter fp_ScreenScaleRefractReflect;
3847         CGparameter fp_ScreenToDepth;
3848         CGparameter fp_ShadowMap_Parameters;
3849         CGparameter fp_ShadowMap_TextureScale;
3850         CGparameter fp_SpecularPower;
3851         CGparameter fp_UserVec1;
3852         CGparameter fp_UserVec2;
3853         CGparameter fp_UserVec3;
3854         CGparameter fp_UserVec4;
3855         CGparameter fp_ViewTintColor;
3856         CGparameter fp_ViewToLight;
3857         CGparameter fp_PixelToScreenTexCoord;
3858         CGparameter fp_ModelToReflectCube;
3859 }
3860 r_cg_permutation_t;
3861
3862 /// information about each possible shader permutation
3863 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3864 /// currently selected permutation
3865 r_cg_permutation_t *r_cg_permutation;
3866 /// storage for permutations linked in the hash table
3867 memexpandablearray_t r_cg_permutationarray;
3868
3869 #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));}}
3870
3871 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3872 {
3873         //unsigned int hashdepth = 0;
3874         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3875         r_cg_permutation_t *p;
3876         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3877         {
3878                 if (p->mode == mode && p->permutation == permutation)
3879                 {
3880                         //if (hashdepth > 10)
3881                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3882                         return p;
3883                 }
3884                 //hashdepth++;
3885         }
3886         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3887         p->mode = mode;
3888         p->permutation = permutation;
3889         p->hashnext = r_cg_permutationhash[mode][hashindex];
3890         r_cg_permutationhash[mode][hashindex] = p;
3891         //if (hashdepth > 10)
3892         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3893         return p;
3894 }
3895
3896 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3897 {
3898         char *shaderstring;
3899         if (!filename || !filename[0])
3900                 return NULL;
3901         if (!strcmp(filename, "cg/default.cg"))
3902         {
3903                 if (!cgshaderstring)
3904                 {
3905                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3906                         if (cgshaderstring)
3907                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3908                         else
3909                                 cgshaderstring = (char *)builtincgshaderstring;
3910                 }
3911                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3912                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3913                 return shaderstring;
3914         }
3915         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3916         if (shaderstring)
3917         {
3918                 if (printfromdisknotice)
3919                         Con_DPrintf("from disk %s... ", filename);
3920                 return shaderstring;
3921         }
3922         return shaderstring;
3923 }
3924
3925 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3926 {
3927         // TODO: load or create .fp and .vp shader files
3928 }
3929
3930 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3931 {
3932         int i;
3933         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3934         int vertstrings_count = 0, vertstring_length = 0;
3935         int geomstrings_count = 0, geomstring_length = 0;
3936         int fragstrings_count = 0, fragstring_length = 0;
3937         char *t;
3938         char *vertexstring, *geometrystring, *fragmentstring;
3939         char *vertstring, *geomstring, *fragstring;
3940         const char *vertstrings_list[32+3];
3941         const char *geomstrings_list[32+3];
3942         const char *fragstrings_list[32+3];
3943         char permutationname[256];
3944         char cachename[256];
3945         CGprofile vertexProfile;
3946         CGprofile fragmentProfile;
3947
3948         if (p->compiled)
3949                 return;
3950         p->compiled = true;
3951         p->vprogram = NULL;
3952         p->fprogram = NULL;
3953
3954         permutationname[0] = 0;
3955         cachename[0] = 0;
3956         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
3957         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
3958         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
3959
3960         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3961         strlcat(cachename, "cg/", sizeof(cachename));
3962
3963         // the first pretext is which type of shader to compile as
3964         // (later these will all be bound together as a program object)
3965         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3966         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3967         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3968
3969         // the second pretext is the mode (for example a light source)
3970         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3971         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3972         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3973         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3974         strlcat(cachename, modeinfo->name, sizeof(cachename));
3975
3976         // now add all the permutation pretexts
3977         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3978         {
3979                 if (permutation & (1<<i))
3980                 {
3981                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3982                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3983                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3984                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3985                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
3986                 }
3987                 else
3988                 {
3989                         // keep line numbers correct
3990                         vertstrings_list[vertstrings_count++] = "\n";
3991                         geomstrings_list[geomstrings_count++] = "\n";
3992                         fragstrings_list[fragstrings_count++] = "\n";
3993                 }
3994         }
3995
3996         // replace spaces in the cachename with _ characters
3997         for (i = 0;cachename[i];i++)
3998                 if (cachename[i] == ' ')
3999                         cachename[i] = '_';
4000
4001         // now append the shader text itself
4002         vertstrings_list[vertstrings_count++] = vertexstring;
4003         geomstrings_list[geomstrings_count++] = geometrystring;
4004         fragstrings_list[fragstrings_count++] = fragmentstring;
4005
4006         // if any sources were NULL, clear the respective list
4007         if (!vertexstring)
4008                 vertstrings_count = 0;
4009         if (!geometrystring)
4010                 geomstrings_count = 0;
4011         if (!fragmentstring)
4012                 fragstrings_count = 0;
4013
4014         vertstring_length = 0;
4015         for (i = 0;i < vertstrings_count;i++)
4016                 vertstring_length += strlen(vertstrings_list[i]);
4017         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4018         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4019                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4020
4021         geomstring_length = 0;
4022         for (i = 0;i < geomstrings_count;i++)
4023                 geomstring_length += strlen(geomstrings_list[i]);
4024         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4025         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4026                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4027
4028         fragstring_length = 0;
4029         for (i = 0;i < fragstrings_count;i++)
4030                 fragstring_length += strlen(fragstrings_list[i]);
4031         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4032         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4033                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4034
4035         CHECKGLERROR
4036         CHECKCGERROR
4037         //vertexProfile = CG_PROFILE_ARBVP1;
4038         //fragmentProfile = CG_PROFILE_ARBFP1;
4039         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4040         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4041         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4042         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4043         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4044         CHECKGLERROR
4045
4046         // try to load the cached shader, or generate one
4047         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4048
4049         // if caching failed, do a dynamic compile for now
4050         CHECKCGERROR
4051         if (vertstring[0] && !p->vprogram)
4052                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4053         CHECKCGERROR
4054         if (fragstring[0] && !p->fprogram)
4055                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4056         CHECKCGERROR
4057
4058         // look up all the uniform variable names we care about, so we don't
4059         // have to look them up every time we set them
4060         if (p->vprogram)
4061         {
4062                 CHECKCGERROR
4063                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4064                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4065                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4066                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4067                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4068                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4069                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4070                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4071                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4072                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4073                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4074                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4075                 CHECKCGERROR
4076         }
4077         if (p->fprogram)
4078         {
4079                 CHECKCGERROR
4080                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4081                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4082                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4083                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4084                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4085                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4086                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4087                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4088                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4089                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4090                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4091                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4092                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4093                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4094                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4095                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4096                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4097                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4098                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4099                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4100                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4101                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4102                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4103                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4104                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4105                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4106                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4107                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4108                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4109                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4110                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4111                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4112                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4113                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4114                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4115                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4116                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4117                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4118                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4119                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4120                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4121                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4122                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4123                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4124                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4125                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4126                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4127                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4128                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4129                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4130                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4131                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4132                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4133                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4134                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4135                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4136                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4137                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4138                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4139                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4140                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4141                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4142                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4143                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4144                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4145                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4146                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4147                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4148                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4149                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4150                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4151                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4152                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4153                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4154                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4155                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4156                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4157                 CHECKCGERROR
4158         }
4159
4160         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4161                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4162         else
4163                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4164
4165         // free the strings
4166         if (vertstring)
4167                 Mem_Free(vertstring);
4168         if (geomstring)
4169                 Mem_Free(geomstring);
4170         if (fragstring)
4171                 Mem_Free(fragstring);
4172         if (vertexstring)
4173                 Mem_Free(vertexstring);
4174         if (geometrystring)
4175                 Mem_Free(geometrystring);
4176         if (fragmentstring)
4177                 Mem_Free(fragmentstring);
4178 }
4179
4180 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4181 {
4182         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4183         CHECKGLERROR
4184         CHECKCGERROR
4185         if (r_cg_permutation != perm)
4186         {
4187                 r_cg_permutation = perm;
4188                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4189                 {
4190                         if (!r_cg_permutation->compiled)
4191                                 R_CG_CompilePermutation(perm, mode, permutation);
4192                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4193                         {
4194                                 // remove features until we find a valid permutation
4195                                 int i;
4196                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4197                                 {
4198                                         // reduce i more quickly whenever it would not remove any bits
4199                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4200                                         if (!(permutation & j))
4201                                                 continue;
4202                                         permutation -= j;
4203                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4204                                         if (!r_cg_permutation->compiled)
4205                                                 R_CG_CompilePermutation(perm, mode, permutation);
4206                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4207                                                 break;
4208                                 }
4209                                 if (i >= SHADERPERMUTATION_COUNT)
4210                                 {
4211                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4212                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4213                                         return; // no bit left to clear, entire mode is broken
4214                                 }
4215                         }
4216                 }
4217                 CHECKGLERROR
4218                 CHECKCGERROR
4219                 if (r_cg_permutation->vprogram)
4220                 {
4221                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4222                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4223                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4224                 }
4225                 else
4226                 {
4227                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4228                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4229                 }
4230                 if (r_cg_permutation->fprogram)
4231                 {
4232                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4233                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4234                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4235                 }
4236                 else
4237                 {
4238                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4239                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4240                 }
4241         }
4242         CHECKCGERROR
4243         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4244         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4245         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4246 }
4247
4248 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4249 {
4250         cgGLSetTextureParameter(param, R_GetTexture(tex));
4251         cgGLEnableTextureParameter(param);
4252 }
4253 #endif
4254
4255 void R_GLSL_Restart_f(void)
4256 {
4257         unsigned int i, limit;
4258         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4259                 Mem_Free(glslshaderstring);
4260         glslshaderstring = NULL;
4261         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4262                 Mem_Free(cgshaderstring);
4263         cgshaderstring = NULL;
4264         switch(vid.renderpath)
4265         {
4266         case RENDERPATH_GL20:
4267                 {
4268                         r_glsl_permutation_t *p;
4269                         r_glsl_permutation = NULL;
4270                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4271                         for (i = 0;i < limit;i++)
4272                         {
4273                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4274                                 {
4275                                         GL_Backend_FreeProgram(p->program);
4276                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4277                                 }
4278                         }
4279                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4280                 }
4281                 break;
4282         case RENDERPATH_CGGL:
4283 #ifdef SUPPORTCG
4284                 {
4285                         r_cg_permutation_t *p;
4286                         r_cg_permutation = NULL;
4287                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4288                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4289                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4290                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4291                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4292                         for (i = 0;i < limit;i++)
4293                         {
4294                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4295                                 {
4296                                         if (p->vprogram)
4297                                                 cgDestroyProgram(p->vprogram);
4298                                         if (p->fprogram)
4299                                                 cgDestroyProgram(p->fprogram);
4300                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4301                                 }
4302                         }
4303                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4304                 }
4305                 break;
4306 #endif
4307         case RENDERPATH_GL13:
4308         case RENDERPATH_GL11:
4309                 break;
4310         }
4311 }
4312
4313 void R_GLSL_DumpShader_f(void)
4314 {
4315         int i;
4316         qfile_t *file;
4317
4318         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4319         if (file)
4320         {
4321                 FS_Print(file, "/* The engine may define the following macros:\n");
4322                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4323                 for (i = 0;i < SHADERMODE_COUNT;i++)
4324                         FS_Print(file, glslshadermodeinfo[i].pretext);
4325                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4326                         FS_Print(file, shaderpermutationinfo[i].pretext);
4327                 FS_Print(file, "*/\n");
4328                 FS_Print(file, builtinshaderstring);
4329                 FS_Close(file);
4330                 Con_Printf("glsl/default.glsl written\n");
4331         }
4332         else
4333                 Con_Printf("failed to write to glsl/default.glsl\n");
4334
4335 #ifdef SUPPORTCG
4336         file = FS_OpenRealFile("cg/default.cg", "w", false);
4337         if (file)
4338         {
4339                 FS_Print(file, "/* The engine may define the following macros:\n");
4340                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4341                 for (i = 0;i < SHADERMODE_COUNT;i++)
4342                         FS_Print(file, cgshadermodeinfo[i].pretext);
4343                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4344                         FS_Print(file, shaderpermutationinfo[i].pretext);
4345                 FS_Print(file, "*/\n");
4346                 FS_Print(file, builtincgshaderstring);
4347                 FS_Close(file);
4348                 Con_Printf("cg/default.cg written\n");
4349         }
4350         else
4351                 Con_Printf("failed to write to cg/default.cg\n");
4352 #endif
4353 }
4354
4355 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4356 {
4357         if (!second)
4358                 texturemode = GL_MODULATE;
4359         switch (vid.renderpath)
4360         {
4361         case RENDERPATH_GL20:
4362                 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))));
4363                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4364                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4365                 break;
4366         case RENDERPATH_CGGL:
4367 #ifdef SUPPORTCG
4368                 CHECKCGERROR
4369                 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))));
4370                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4371                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4372 #endif
4373                 break;
4374         case RENDERPATH_GL13:
4375                 R_Mesh_TexBind(0, first );
4376                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4377                 R_Mesh_TexBind(1, second);
4378                 if (second)
4379                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4380                 break;
4381         case RENDERPATH_GL11:
4382                 R_Mesh_TexBind(0, first );
4383                 break;
4384         }
4385 }
4386
4387 void R_SetupShader_DepthOrShadow(void)
4388 {
4389         switch (vid.renderpath)
4390         {
4391         case RENDERPATH_GL20:
4392                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4393                 break;
4394         case RENDERPATH_CGGL:
4395 #ifdef SUPPORTCG
4396                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4397 #endif
4398                 break;
4399         case RENDERPATH_GL13:
4400                 R_Mesh_TexBind(0, 0);
4401                 R_Mesh_TexBind(1, 0);
4402                 break;
4403         case RENDERPATH_GL11:
4404                 R_Mesh_TexBind(0, 0);
4405                 break;
4406         }
4407 }
4408
4409 void R_SetupShader_ShowDepth(void)
4410 {
4411         switch (vid.renderpath)
4412         {
4413         case RENDERPATH_GL20:
4414                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4415                 break;
4416         case RENDERPATH_CGGL:
4417 #ifdef SUPPORTCG
4418                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4419 #endif
4420                 break;
4421         case RENDERPATH_GL13:
4422                 break;
4423         case RENDERPATH_GL11:
4424                 break;
4425         }
4426 }
4427
4428 extern qboolean r_shadow_usingdeferredprepass;
4429 extern cvar_t r_shadow_deferred_8bitrange;
4430 extern rtexture_t *r_shadow_attenuationgradienttexture;
4431 extern rtexture_t *r_shadow_attenuation2dtexture;
4432 extern rtexture_t *r_shadow_attenuation3dtexture;
4433 extern qboolean r_shadow_usingshadowmaprect;
4434 extern qboolean r_shadow_usingshadowmapcube;
4435 extern qboolean r_shadow_usingshadowmap2d;
4436 extern qboolean r_shadow_usingshadowmaportho;
4437 extern float r_shadow_shadowmap_texturescale[2];
4438 extern float r_shadow_shadowmap_parameters[4];
4439 extern qboolean r_shadow_shadowmapvsdct;
4440 extern qboolean r_shadow_shadowmapsampler;
4441 extern int r_shadow_shadowmappcf;
4442 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4443 extern rtexture_t *r_shadow_shadowmap2dtexture;
4444 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4445 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4446 extern matrix4x4_t r_shadow_shadowmapmatrix;
4447 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4448 extern int r_shadow_prepass_width;
4449 extern int r_shadow_prepass_height;
4450 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4451 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4452 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4453 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4454 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass)
4455 {
4456         // select a permutation of the lighting shader appropriate to this
4457         // combination of texture, entity, light source, and fogging, only use the
4458         // minimum features necessary to avoid wasting rendering time in the
4459         // fragment shader on features that are not being used
4460         unsigned int permutation = 0;
4461         unsigned int mode = 0;
4462         float m16f[16];
4463         if (rsurfacepass == RSURFPASS_BACKGROUND)
4464         {
4465                 // distorted background
4466                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4467                         mode = SHADERMODE_WATER;
4468                 else
4469                         mode = SHADERMODE_REFRACTION;
4470                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4471                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4472                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4473                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4474                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4475                 R_Mesh_ColorPointer(NULL, 0, 0);
4476                 GL_AlphaTest(false);
4477                 GL_BlendFunc(GL_ONE, GL_ZERO);
4478         }
4479         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4480         {
4481                 if (r_glsl_offsetmapping.integer)
4482                 {
4483                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4484                         if (r_glsl_offsetmapping_reliefmapping.integer)
4485                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4486                 }
4487                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4488                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4489                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4490                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4491                 // normalmap (deferred prepass), may use alpha test on diffuse
4492                 mode = SHADERMODE_DEFERREDGEOMETRY;
4493                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4494                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4495                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4496                 R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4497                 R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4498                 R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4499                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4500                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4501                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4502                 else
4503                         R_Mesh_ColorPointer(NULL, 0, 0);
4504                 GL_AlphaTest(false);
4505                 GL_BlendFunc(GL_ONE, GL_ZERO);
4506         }
4507         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4508         {
4509                 if (r_glsl_offsetmapping.integer)
4510                 {
4511                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4512                         if (r_glsl_offsetmapping_reliefmapping.integer)
4513                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4514                 }
4515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4516                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4517                 // light source
4518                 mode = SHADERMODE_LIGHTSOURCE;
4519                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4520                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4521                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4522                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4523                 if (diffusescale > 0)
4524                         permutation |= SHADERPERMUTATION_DIFFUSE;
4525                 if (specularscale > 0)
4526                 {
4527                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4528                         if (r_shadow_glossexact.integer)
4529                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4530                 }
4531                 if (r_refdef.fogenabled)
4532                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4533                 if (rsurface.texture->colormapping)
4534                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4535                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4536                 {
4537                         if (r_shadow_usingshadowmaprect)
4538                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4539                         if (r_shadow_usingshadowmap2d)
4540                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4541                         if (r_shadow_usingshadowmapcube)
4542                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4543                         else if(r_shadow_shadowmapvsdct)
4544                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4545
4546                         if (r_shadow_shadowmapsampler)
4547                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4548                         if (r_shadow_shadowmappcf > 1)
4549                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4550                         else if (r_shadow_shadowmappcf)
4551                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4552                 }
4553                 if (rsurface.texture->reflectmasktexture)
4554                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4555                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4556                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4557                 {
4558                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4559                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4560                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4561                 }
4562                 else
4563                 {
4564                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4565                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4566                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4567                 }
4568                 //R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4569                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4570                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4571                 else
4572                         R_Mesh_ColorPointer(NULL, 0, 0);
4573                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4574                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4575         }
4576         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4577         {
4578                 if (r_glsl_offsetmapping.integer)
4579                 {
4580                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4581                         if (r_glsl_offsetmapping_reliefmapping.integer)
4582                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4583                 }
4584                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4585                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4586                 // unshaded geometry (fullbright or ambient model lighting)
4587                 mode = SHADERMODE_FLATCOLOR;
4588                 ambientscale = diffusescale = specularscale = 0;
4589                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4590                         permutation |= SHADERPERMUTATION_GLOW;
4591                 if (r_refdef.fogenabled)
4592                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4593                 if (rsurface.texture->colormapping)
4594                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4595                 if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
4596                 {
4597                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4598                         if (r_shadow_usingshadowmaprect)
4599                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4600                         if (r_shadow_usingshadowmap2d)
4601                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4602
4603                         if (r_shadow_shadowmapsampler)
4604                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4605                         if (r_shadow_shadowmappcf > 1)
4606                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4607                         else if (r_shadow_shadowmappcf)
4608                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4609                 }
4610                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4611                         permutation |= SHADERPERMUTATION_REFLECTION;
4612                 if (rsurface.texture->reflectmasktexture)
4613                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4614                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4615                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4616                 {
4617                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4618                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4619                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4620                 }
4621                 else
4622                 {
4623                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4624                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4625                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4626                 }
4627                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4629                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4630                 else
4631                         R_Mesh_ColorPointer(NULL, 0, 0);
4632                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4633                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4634         }
4635         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4636         {
4637                 if (r_glsl_offsetmapping.integer)
4638                 {
4639                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4640                         if (r_glsl_offsetmapping_reliefmapping.integer)
4641                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4642                 }
4643                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4644                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4645                 // directional model lighting
4646                 mode = SHADERMODE_LIGHTDIRECTION;
4647                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4648                         permutation |= SHADERPERMUTATION_GLOW;
4649                 permutation |= SHADERPERMUTATION_DIFFUSE;
4650                 if (specularscale > 0)
4651                 {
4652                         permutation |= SHADERPERMUTATION_SPECULAR;
4653                         if (r_shadow_glossexact.integer)
4654                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4655                 }
4656                 if (r_refdef.fogenabled)
4657                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4658                 if (rsurface.texture->colormapping)
4659                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4660                 if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
4661                 {
4662                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4663                         if (r_shadow_usingshadowmaprect)
4664                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4665                         if (r_shadow_usingshadowmap2d)
4666                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4667
4668                         if (r_shadow_shadowmapsampler)
4669                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4670                         if (r_shadow_shadowmappcf > 1)
4671                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4672                         else if (r_shadow_shadowmappcf)
4673                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4674                 }
4675                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4676                         permutation |= SHADERPERMUTATION_REFLECTION;
4677                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4678                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4679                 if (rsurface.texture->reflectmasktexture)
4680                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4681                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4682                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4683                 {
4684                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4685                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4686                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4687                 }
4688                 else
4689                 {
4690                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4691                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4692                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4693                 }
4694                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4695                 R_Mesh_ColorPointer(NULL, 0, 0);
4696                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4697                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4698         }
4699         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4700         {
4701                 if (r_glsl_offsetmapping.integer)
4702                 {
4703                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4704                         if (r_glsl_offsetmapping_reliefmapping.integer)
4705                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4706                 }
4707                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4708                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4709                 // ambient model lighting
4710                 mode = SHADERMODE_LIGHTDIRECTION;
4711                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4712                         permutation |= SHADERPERMUTATION_GLOW;
4713                 if (r_refdef.fogenabled)
4714                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4715                 if (rsurface.texture->colormapping)
4716                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4717                 if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
4718                 {
4719                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4720                         if (r_shadow_usingshadowmaprect)
4721                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4722                         if (r_shadow_usingshadowmap2d)
4723                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4724
4725                         if (r_shadow_shadowmapsampler)
4726                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4727                         if (r_shadow_shadowmappcf > 1)
4728                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4729                         else if (r_shadow_shadowmappcf)
4730                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4731                 }
4732                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4733                         permutation |= SHADERPERMUTATION_REFLECTION;
4734                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4735                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4736                 if (rsurface.texture->reflectmasktexture)
4737                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4738                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4739                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4740                 {
4741                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4742                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4743                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4744                 }
4745                 else
4746                 {
4747                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4748                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4749                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4750                 }
4751                 R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4752                 R_Mesh_ColorPointer(NULL, 0, 0);
4753                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4754                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4755         }
4756         else
4757         {
4758                 if (r_glsl_offsetmapping.integer)
4759                 {
4760                         permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4761                         if (r_glsl_offsetmapping_reliefmapping.integer)
4762                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4763                 }
4764                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4765                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4766                 // lightmapped wall
4767                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4768                         permutation |= SHADERPERMUTATION_GLOW;
4769                 if (r_refdef.fogenabled)
4770                         permutation |= r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE;
4771                 if (rsurface.texture->colormapping)
4772                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4773                 if (r_shadow_usingshadowmaportho && (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d))
4774                 {
4775                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4776                         if (r_shadow_usingshadowmaprect)
4777                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4778                         if (r_shadow_usingshadowmap2d)
4779                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4780
4781                         if (r_shadow_shadowmapsampler)
4782                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4783                         if (r_shadow_shadowmappcf > 1)
4784                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4785                         else if (r_shadow_shadowmappcf)
4786                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4787                 }
4788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4789                         permutation |= SHADERPERMUTATION_REFLECTION;
4790                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4791                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4792                 if (rsurface.texture->reflectmasktexture)
4793                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4794                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4795                 {
4796                         // deluxemapping (light direction texture)
4797                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4798                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4799                         else
4800                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4801                         permutation |= SHADERPERMUTATION_DIFFUSE;
4802                         if (specularscale > 0)
4803                         {
4804                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4805                                 if (r_shadow_glossexact.integer)
4806                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4807                         }
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 if (r_glsl_deluxemapping.integer >= 2)
4815                 {
4816                         // fake deluxemapping (uniform light direction in tangentspace)
4817                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4818                         permutation |= SHADERPERMUTATION_DIFFUSE;
4819                         if (specularscale > 0)
4820                         {
4821                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4822                                 if (r_shadow_glossexact.integer)
4823                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4824                         }
4825                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4826                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4827                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4828                         else
4829                                 R_Mesh_ColorPointer(NULL, 0, 0);
4830                 }
4831                 else if (rsurface.uselightmaptexture)
4832                 {
4833                         // ordinary lightmapping (q1bsp, q3bsp)
4834                         mode = SHADERMODE_LIGHTMAP;
4835                         R_Mesh_TexCoordPointer(4, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
4836                         if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND)
4837                                 R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4838                         else
4839                                 R_Mesh_ColorPointer(NULL, 0, 0);
4840                 }
4841                 else
4842                 {
4843                         // ordinary vertex coloring (q3bsp)
4844                         mode = SHADERMODE_VERTEXCOLOR;
4845                         R_Mesh_TexCoordPointer(4, 0, NULL, 0, 0);
4846                         R_Mesh_ColorPointer(rsurface.modellightmapcolor4f, rsurface.modellightmapcolor4f_bufferobject, rsurface.modellightmapcolor4f_bufferoffset);
4847                 }
4848                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
4849                 if (true || permutation & (SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_OFFSETMAPPING))
4850                 {
4851                         R_Mesh_TexCoordPointer(1, 3, rsurface.svector3f, rsurface.svector3f_bufferobject, rsurface.svector3f_bufferoffset);
4852                         R_Mesh_TexCoordPointer(2, 3, rsurface.tvector3f, rsurface.tvector3f_bufferobject, rsurface.tvector3f_bufferoffset);
4853                         R_Mesh_TexCoordPointer(3, 3, rsurface.normal3f, rsurface.normal3f_bufferobject, rsurface.normal3f_bufferoffset);
4854                 }
4855                 else
4856                 {
4857                         R_Mesh_TexCoordPointer(1, 0, NULL, 0, 0);
4858                         R_Mesh_TexCoordPointer(2, 0, NULL, 0, 0);
4859                         R_Mesh_TexCoordPointer(3, 0, NULL, 0, 0);
4860                 }
4861                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4862                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4863         }
4864         switch(vid.renderpath)
4865         {
4866         case RENDERPATH_GL20:
4867                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4868                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4869                 if (mode == SHADERMODE_LIGHTSOURCE)
4870                 {
4871                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4872                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4873                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4874                         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);
4875                         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);
4876                         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);
4877         
4878                         // additive passes are only darkened by fog, not tinted
4879                         if (r_glsl_permutation->loc_FogColor >= 0)
4880                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4881                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4882                 }
4883                 else
4884                 {
4885                         if (mode == SHADERMODE_FLATCOLOR)
4886                         {
4887                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4888                         }
4889                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4890                         {
4891                                 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]);
4892                                 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]);
4893                                 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);
4894                                 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);
4895                                 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);
4896                                 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]);
4897                                 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]);
4898                         }
4899                         else
4900                         {
4901                                 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]);
4902                                 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]);
4903                                 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);
4904                                 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);
4905                                 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);
4906                         }
4907                         // additive passes are only darkened by fog, not tinted
4908                         if (r_glsl_permutation->loc_FogColor >= 0)
4909                         {
4910                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4911                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4912                                 else
4913                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4914                         }
4915                         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);
4916                         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]);
4917                         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]);
4918                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4919                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4920                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4921                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4922                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4923                 }
4924                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4925                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4926                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4927                 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]);
4928                 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]);
4929
4930                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4931                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4932                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4933                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4934                 {
4935                         if (rsurface.texture->pantstexture)
4936                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4937                         else
4938                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4939                 }
4940                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4941                 {
4942                         if (rsurface.texture->shirttexture)
4943                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4944                         else
4945                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4946                 }
4947                 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]);
4948                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4949                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4950                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4951                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
4952                 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]);
4953                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
4954
4955         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
4956         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
4957         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
4958                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
4959                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
4960                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
4961                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
4962                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
4963                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
4964                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
4965                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
4966                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
4967                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
4968                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
4969                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
4970                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
4971                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
4972                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
4973                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
4974                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
4975                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
4976                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
4977                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
4978                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
4979                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
4980                 if (rsurface.rtlight || r_shadow_usingshadowmaportho)
4981                 {
4982                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D       , r_shadow_shadowmap2dtexture                         );
4983                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT     , r_shadow_shadowmaprectangletexture                  );
4984                         if (rsurface.rtlight)
4985                         {
4986                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
4987                                 if (r_shadow_usingshadowmapcube)
4988                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
4989                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
4990                         }
4991                 }
4992                 CHECKGLERROR
4993                 break;
4994         case RENDERPATH_CGGL:
4995 #ifdef SUPPORTCG
4996                 R_SetupShader_SetPermutationCG(mode, permutation);
4997                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
4998                 if (mode == SHADERMODE_LIGHTSOURCE)
4999                 {
5000                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5001                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5002                 }
5003                 else
5004                 {
5005                         if (mode == SHADERMODE_LIGHTDIRECTION)
5006                         {
5007                                 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
5008                         }
5009                 }
5010                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5011                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5012                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5013                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5014                 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
5015                 CHECKGLERROR
5016
5017                 if (mode == SHADERMODE_LIGHTSOURCE)
5018                 {
5019                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5020                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5021                         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
5022                         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
5023                         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
5024
5025                         // additive passes are only darkened by fog, not tinted
5026                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5027                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5028                 }
5029                 else
5030                 {
5031                         if (mode == SHADERMODE_FLATCOLOR)
5032                         {
5033                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5034                         }
5035                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5036                         {
5037                                 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
5038                                 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
5039                                 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
5040                                 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
5041                                 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
5042                                 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
5043                                 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
5044                         }
5045                         else
5046                         {
5047                                 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
5048                                 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
5049                                 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
5050                                 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
5051                                 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
5052                         }
5053                         // additive passes are only darkened by fog, not tinted
5054                         if (r_cg_permutation->fp_FogColor)
5055                         {
5056                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5057                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5058                                 else
5059                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5060                                 CHECKCGERROR
5061                         }
5062                         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
5063                         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
5064                         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
5065                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5066                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5067                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5068                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5069                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5070                 }
5071                 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
5072                 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
5073                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5074                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5075                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5076                 if (r_cg_permutation->fp_Color_Pants)
5077                 {
5078                         if (rsurface.texture->pantstexture)
5079                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5080                         else
5081                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5082                         CHECKCGERROR
5083                 }
5084                 if (r_cg_permutation->fp_Color_Shirt)
5085                 {
5086                         if (rsurface.texture->shirttexture)
5087                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5088                         else
5089                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5090                         CHECKCGERROR
5091                 }
5092                 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
5093                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5094                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5095                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5096                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5097                 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
5098                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5099
5100         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5101         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5102         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5103                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5104                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5105                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5106                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5107                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5108                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5109                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5110                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5111                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5112                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5113                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5114                 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
5115                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5116                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5117                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5118                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5119                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5120                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5121                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5122                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5123                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5124                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5125                 if (rsurface.rtlight || r_shadow_usingshadowmaportho)
5126                 {
5127                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5128                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5129                         if (rsurface.rtlight)
5130                         {
5131                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5132                                 if (r_shadow_usingshadowmapcube)
5133                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5134                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5135                         }
5136                 }
5137
5138                 CHECKGLERROR
5139 #endif
5140                 break;
5141         case RENDERPATH_GL13:
5142         case RENDERPATH_GL11:
5143                 break;
5144         }
5145 }
5146
5147 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5148 {
5149         // select a permutation of the lighting shader appropriate to this
5150         // combination of texture, entity, light source, and fogging, only use the
5151         // minimum features necessary to avoid wasting rendering time in the
5152         // fragment shader on features that are not being used
5153         unsigned int permutation = 0;
5154         unsigned int mode = 0;
5155         const float *lightcolorbase = rtlight->currentcolor;
5156         float ambientscale = rtlight->ambientscale;
5157         float diffusescale = rtlight->diffusescale;
5158         float specularscale = rtlight->specularscale;
5159         // this is the location of the light in view space
5160         vec3_t viewlightorigin;
5161         // this transforms from view space (camera) to light space (cubemap)
5162         matrix4x4_t viewtolight;
5163         matrix4x4_t lighttoview;
5164         float viewtolight16f[16];
5165         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5166         // light source
5167         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5168         if (rtlight->currentcubemap != r_texture_whitecube)
5169                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5170         if (diffusescale > 0)
5171                 permutation |= SHADERPERMUTATION_DIFFUSE;
5172         if (specularscale > 0)
5173         {
5174                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5175                 if (r_shadow_glossexact.integer)
5176                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5177         }
5178         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5179         {
5180                 if (r_shadow_usingshadowmaprect)
5181                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5182                 if (r_shadow_usingshadowmap2d)
5183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5184                 if (r_shadow_usingshadowmapcube)
5185                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5186                 else if(r_shadow_shadowmapvsdct)
5187                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5188
5189                 if (r_shadow_shadowmapsampler)
5190                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5191                 if (r_shadow_shadowmappcf > 1)
5192                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5193                 else if (r_shadow_shadowmappcf)
5194                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5195         }
5196         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5197         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5198         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5199         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5200         switch(vid.renderpath)
5201         {
5202         case RENDERPATH_GL20:
5203                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5204                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5205                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5206                 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);
5207                 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);
5208                 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);
5209                 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]);
5210                 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]);
5211                 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));
5212                 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]);
5213                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5214
5215                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5216                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5217                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5218                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5219                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5220                 if (r_shadow_usingshadowmapcube)
5221                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5222                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5223                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5224                 break;
5225         case RENDERPATH_CGGL:
5226 #ifdef SUPPORTCG
5227                 R_SetupShader_SetPermutationCG(mode, permutation);
5228                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5229                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5230                 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
5231                 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
5232                 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
5233                 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
5234                 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
5235                 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
5236                 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
5237                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5238
5239                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5240                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5241                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5242                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5243                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5244                 if (r_shadow_usingshadowmapcube)
5245                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5246                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5247                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5248 #endif
5249                 break;
5250         case RENDERPATH_GL13:
5251         case RENDERPATH_GL11:
5252                 break;
5253         }
5254 }
5255
5256 #define SKINFRAME_HASH 1024
5257
5258 typedef struct
5259 {
5260         int loadsequence; // incremented each level change
5261         memexpandablearray_t array;
5262         skinframe_t *hash[SKINFRAME_HASH];
5263 }
5264 r_skinframe_t;
5265 r_skinframe_t r_skinframe;
5266
5267 void R_SkinFrame_PrepareForPurge(void)
5268 {
5269         r_skinframe.loadsequence++;
5270         // wrap it without hitting zero
5271         if (r_skinframe.loadsequence >= 200)
5272                 r_skinframe.loadsequence = 1;
5273 }
5274
5275 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5276 {
5277         if (!skinframe)
5278                 return;
5279         // mark the skinframe as used for the purging code
5280         skinframe->loadsequence = r_skinframe.loadsequence;
5281 }
5282
5283 void R_SkinFrame_Purge(void)
5284 {
5285         int i;
5286         skinframe_t *s;
5287         for (i = 0;i < SKINFRAME_HASH;i++)
5288         {
5289                 for (s = r_skinframe.hash[i];s;s = s->next)
5290                 {
5291                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5292                         {
5293                                 if (s->merged == s->base)
5294                                         s->merged = NULL;
5295                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5296                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5297                                 R_PurgeTexture(s->merged);s->merged = NULL;
5298                                 R_PurgeTexture(s->base  );s->base   = NULL;
5299                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5300                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5301                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5302                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5303                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5304                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5305                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5306                                 s->loadsequence = 0;
5307                         }
5308                 }
5309         }
5310 }
5311
5312 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5313         skinframe_t *item;
5314         char basename[MAX_QPATH];
5315
5316         Image_StripImageExtension(name, basename, sizeof(basename));
5317
5318         if( last == NULL ) {
5319                 int hashindex;
5320                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5321                 item = r_skinframe.hash[hashindex];
5322         } else {
5323                 item = last->next;
5324         }
5325
5326         // linearly search through the hash bucket
5327         for( ; item ; item = item->next ) {
5328                 if( !strcmp( item->basename, basename ) ) {
5329                         return item;
5330                 }
5331         }
5332         return NULL;
5333 }
5334
5335 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5336 {
5337         skinframe_t *item;
5338         int hashindex;
5339         char basename[MAX_QPATH];
5340
5341         Image_StripImageExtension(name, basename, sizeof(basename));
5342
5343         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5344         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5345                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5346                         break;
5347
5348         if (!item) {
5349                 rtexture_t *dyntexture;
5350                 // check whether its a dynamic texture
5351                 dyntexture = CL_GetDynTexture( basename );
5352                 if (!add && !dyntexture)
5353                         return NULL;
5354                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5355                 memset(item, 0, sizeof(*item));
5356                 strlcpy(item->basename, basename, sizeof(item->basename));
5357                 item->base = dyntexture; // either NULL or dyntexture handle
5358                 item->textureflags = textureflags;
5359                 item->comparewidth = comparewidth;
5360                 item->compareheight = compareheight;
5361                 item->comparecrc = comparecrc;
5362                 item->next = r_skinframe.hash[hashindex];
5363                 r_skinframe.hash[hashindex] = item;
5364         }
5365         else if( item->base == NULL )
5366         {
5367                 rtexture_t *dyntexture;
5368                 // check whether its a dynamic texture
5369                 // 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]
5370                 dyntexture = CL_GetDynTexture( basename );
5371                 item->base = dyntexture; // either NULL or dyntexture handle
5372         }
5373
5374         R_SkinFrame_MarkUsed(item);
5375         return item;
5376 }
5377
5378 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5379         { \
5380                 unsigned long long avgcolor[5], wsum; \
5381                 int pix, comp, w; \
5382                 avgcolor[0] = 0; \
5383                 avgcolor[1] = 0; \
5384                 avgcolor[2] = 0; \
5385                 avgcolor[3] = 0; \
5386                 avgcolor[4] = 0; \
5387                 wsum = 0; \
5388                 for(pix = 0; pix < cnt; ++pix) \
5389                 { \
5390                         w = 0; \
5391                         for(comp = 0; comp < 3; ++comp) \
5392                                 w += getpixel; \
5393                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5394                         { \
5395                                 ++wsum; \
5396                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5397                                 w = getpixel; \
5398                                 for(comp = 0; comp < 3; ++comp) \
5399                                         avgcolor[comp] += getpixel * w; \
5400                                 avgcolor[3] += w; \
5401                         } \
5402                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5403                         avgcolor[4] += getpixel; \
5404                 } \
5405                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5406                         avgcolor[3] = 1; \
5407                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5408                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5409                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5410                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5411         }
5412
5413 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5414 {
5415         int j;
5416         unsigned char *pixels;
5417         unsigned char *bumppixels;
5418         unsigned char *basepixels = NULL;
5419         int basepixels_width = 0;
5420         int basepixels_height = 0;
5421         skinframe_t *skinframe;
5422         rtexture_t *ddsbase = NULL;
5423         qboolean ddshasalpha = false;
5424         float ddsavgcolor[4];
5425         char basename[MAX_QPATH];
5426
5427         if (cls.state == ca_dedicated)
5428                 return NULL;
5429
5430         // return an existing skinframe if already loaded
5431         // if loading of the first image fails, don't make a new skinframe as it
5432         // would cause all future lookups of this to be missing
5433         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5434         if (skinframe && skinframe->base)
5435                 return skinframe;
5436
5437         Image_StripImageExtension(name, basename, sizeof(basename));
5438
5439         // check for DDS texture file first
5440         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5441         {
5442                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5443                 if (basepixels == NULL)
5444                         return NULL;
5445         }
5446
5447         if (developer_loading.integer)
5448                 Con_Printf("loading skin \"%s\"\n", name);
5449
5450         // we've got some pixels to store, so really allocate this new texture now
5451         if (!skinframe)
5452                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5453         skinframe->stain = NULL;
5454         skinframe->merged = NULL;
5455         skinframe->base = NULL;
5456         skinframe->pants = NULL;
5457         skinframe->shirt = NULL;
5458         skinframe->nmap = NULL;
5459         skinframe->gloss = NULL;
5460         skinframe->glow = NULL;
5461         skinframe->fog = NULL;
5462         skinframe->reflect = NULL;
5463         skinframe->hasalpha = false;
5464
5465         if (ddsbase)
5466         {
5467                 skinframe->base = ddsbase;
5468                 skinframe->hasalpha = ddshasalpha;
5469                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5470                 if (r_loadfog && skinframe->hasalpha)
5471                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5472                 //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]);
5473         }
5474         else
5475         {
5476                 basepixels_width = image_width;
5477                 basepixels_height = image_height;
5478                 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);
5479                 if (textureflags & TEXF_ALPHA)
5480                 {
5481                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5482                         {
5483                                 if (basepixels[j] < 255)
5484                                 {
5485                                         skinframe->hasalpha = true;
5486                                         break;
5487                                 }
5488                         }
5489                         if (r_loadfog && skinframe->hasalpha)
5490                         {
5491                                 // has transparent pixels
5492                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5493                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5494                                 {
5495                                         pixels[j+0] = 255;
5496                                         pixels[j+1] = 255;
5497                                         pixels[j+2] = 255;
5498                                         pixels[j+3] = basepixels[j+3];
5499                                 }
5500                                 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);
5501                                 Mem_Free(pixels);
5502                         }
5503                 }
5504                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5505                 //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]);
5506                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5507                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5508                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5509                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5510         }
5511
5512         if (r_loaddds)
5513         {
5514                 if (r_loadnormalmap)
5515                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5516                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5517                 if (r_loadgloss)
5518                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5519                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5520                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5521                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5522         }
5523
5524         // _norm is the name used by tenebrae and has been adopted as standard
5525         if (r_loadnormalmap && skinframe->nmap == NULL)
5526         {
5527                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5528                 {
5529                         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);
5530                         Mem_Free(pixels);
5531                         pixels = NULL;
5532                 }
5533                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5534                 {
5535                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5536                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5537                         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);
5538                         Mem_Free(pixels);
5539                         Mem_Free(bumppixels);
5540                 }
5541                 else if (r_shadow_bumpscale_basetexture.value > 0)
5542                 {
5543                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5544                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5545                         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);
5546                         Mem_Free(pixels);
5547                 }
5548                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5549                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5550         }
5551
5552         // _luma is supported only for tenebrae compatibility
5553         // _glow is the preferred name
5554         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))))
5555         {
5556                 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);
5557                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5558                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5559                 Mem_Free(pixels);pixels = NULL;
5560         }
5561
5562         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5563         {
5564                 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);
5565                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5566                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5567                 Mem_Free(pixels);
5568                 pixels = NULL;
5569         }
5570
5571         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5572         {
5573                 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);
5574                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5575                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5576                 Mem_Free(pixels);
5577                 pixels = NULL;
5578         }
5579
5580         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5581         {
5582                 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);
5583                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5584                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5585                 Mem_Free(pixels);
5586                 pixels = NULL;
5587         }
5588
5589         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5590         {
5591                 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);
5592                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5593                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5594                 Mem_Free(pixels);
5595                 pixels = NULL;
5596         }
5597
5598         if (basepixels)
5599                 Mem_Free(basepixels);
5600
5601         return skinframe;
5602 }
5603
5604 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5605 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5606 {
5607         int i;
5608         unsigned char *temp1, *temp2;
5609         skinframe_t *skinframe;
5610
5611         if (cls.state == ca_dedicated)
5612                 return NULL;
5613
5614         // if already loaded just return it, otherwise make a new skinframe
5615         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5616         if (skinframe && skinframe->base)
5617                 return skinframe;
5618
5619         skinframe->stain = NULL;
5620         skinframe->merged = NULL;
5621         skinframe->base = NULL;
5622         skinframe->pants = NULL;
5623         skinframe->shirt = NULL;
5624         skinframe->nmap = NULL;
5625         skinframe->gloss = NULL;
5626         skinframe->glow = NULL;
5627         skinframe->fog = NULL;
5628         skinframe->reflect = NULL;
5629         skinframe->hasalpha = false;
5630
5631         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5632         if (!skindata)
5633                 return NULL;
5634
5635         if (developer_loading.integer)
5636                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5637
5638         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5639         {
5640                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5641                 temp2 = temp1 + width * height * 4;
5642                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5643                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5644                 Mem_Free(temp1);
5645         }
5646         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5647         if (textureflags & TEXF_ALPHA)
5648         {
5649                 for (i = 3;i < width * height * 4;i += 4)
5650                 {
5651                         if (skindata[i] < 255)
5652                         {
5653                                 skinframe->hasalpha = true;
5654                                 break;
5655                         }
5656                 }
5657                 if (r_loadfog && skinframe->hasalpha)
5658                 {
5659                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5660                         memcpy(fogpixels, skindata, width * height * 4);
5661                         for (i = 0;i < width * height * 4;i += 4)
5662                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5663                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5664                         Mem_Free(fogpixels);
5665                 }
5666         }
5667
5668         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5669         //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]);
5670
5671         return skinframe;
5672 }
5673
5674 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5675 {
5676         int i;
5677         int featuresmask;
5678         skinframe_t *skinframe;
5679
5680         if (cls.state == ca_dedicated)
5681                 return NULL;
5682
5683         // if already loaded just return it, otherwise make a new skinframe
5684         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5685         if (skinframe && skinframe->base)
5686                 return skinframe;
5687
5688         skinframe->stain = NULL;
5689         skinframe->merged = NULL;
5690         skinframe->base = NULL;
5691         skinframe->pants = NULL;
5692         skinframe->shirt = NULL;
5693         skinframe->nmap = NULL;
5694         skinframe->gloss = NULL;
5695         skinframe->glow = NULL;
5696         skinframe->fog = NULL;
5697         skinframe->reflect = NULL;
5698         skinframe->hasalpha = false;
5699
5700         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5701         if (!skindata)
5702                 return NULL;
5703
5704         if (developer_loading.integer)
5705                 Con_Printf("loading quake skin \"%s\"\n", name);
5706
5707         // 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)
5708         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5709         memcpy(skinframe->qpixels, skindata, width*height);
5710         skinframe->qwidth = width;
5711         skinframe->qheight = height;
5712
5713         featuresmask = 0;
5714         for (i = 0;i < width * height;i++)
5715                 featuresmask |= palette_featureflags[skindata[i]];
5716
5717         skinframe->hasalpha = false;
5718         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5719         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5720         skinframe->qgeneratemerged = true;
5721         skinframe->qgeneratebase = skinframe->qhascolormapping;
5722         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5723
5724         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5725         //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]);
5726
5727         return skinframe;
5728 }
5729
5730 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5731 {
5732         int width;
5733         int height;
5734         unsigned char *skindata;
5735
5736         if (!skinframe->qpixels)
5737                 return;
5738
5739         if (!skinframe->qhascolormapping)
5740                 colormapped = false;
5741
5742         if (colormapped)
5743         {
5744                 if (!skinframe->qgeneratebase)
5745                         return;
5746         }
5747         else
5748         {
5749                 if (!skinframe->qgeneratemerged)
5750                         return;
5751         }
5752
5753         width = skinframe->qwidth;
5754         height = skinframe->qheight;
5755         skindata = skinframe->qpixels;
5756
5757         if (skinframe->qgeneratenmap)
5758         {
5759                 unsigned char *temp1, *temp2;
5760                 skinframe->qgeneratenmap = false;
5761                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5762                 temp2 = temp1 + width * height * 4;
5763                 // use either a custom palette or the quake palette
5764                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5765                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5766                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5767                 Mem_Free(temp1);
5768         }
5769
5770         if (skinframe->qgenerateglow)
5771         {
5772                 skinframe->qgenerateglow = false;
5773                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5774         }
5775
5776         if (colormapped)
5777         {
5778                 skinframe->qgeneratebase = false;
5779                 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);
5780                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5781                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5782         }
5783         else
5784         {
5785                 skinframe->qgeneratemerged = false;
5786                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5787         }
5788
5789         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5790         {
5791                 Mem_Free(skinframe->qpixels);
5792                 skinframe->qpixels = NULL;
5793         }
5794 }
5795
5796 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)
5797 {
5798         int i;
5799         skinframe_t *skinframe;
5800
5801         if (cls.state == ca_dedicated)
5802                 return NULL;
5803
5804         // if already loaded just return it, otherwise make a new skinframe
5805         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5806         if (skinframe && skinframe->base)
5807                 return skinframe;
5808
5809         skinframe->stain = NULL;
5810         skinframe->merged = NULL;
5811         skinframe->base = NULL;
5812         skinframe->pants = NULL;
5813         skinframe->shirt = NULL;
5814         skinframe->nmap = NULL;
5815         skinframe->gloss = NULL;
5816         skinframe->glow = NULL;
5817         skinframe->fog = NULL;
5818         skinframe->reflect = NULL;
5819         skinframe->hasalpha = false;
5820
5821         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5822         if (!skindata)
5823                 return NULL;
5824
5825         if (developer_loading.integer)
5826                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5827
5828         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5829         if (textureflags & TEXF_ALPHA)
5830         {
5831                 for (i = 0;i < width * height;i++)
5832                 {
5833                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5834                         {
5835                                 skinframe->hasalpha = true;
5836                                 break;
5837                         }
5838                 }
5839                 if (r_loadfog && skinframe->hasalpha)
5840                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5841         }
5842
5843         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5844         //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]);
5845
5846         return skinframe;
5847 }
5848
5849 skinframe_t *R_SkinFrame_LoadMissing(void)
5850 {
5851         skinframe_t *skinframe;
5852
5853         if (cls.state == ca_dedicated)
5854                 return NULL;
5855
5856         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5857         skinframe->stain = NULL;
5858         skinframe->merged = NULL;
5859         skinframe->base = NULL;
5860         skinframe->pants = NULL;
5861         skinframe->shirt = NULL;
5862         skinframe->nmap = NULL;
5863         skinframe->gloss = NULL;
5864         skinframe->glow = NULL;
5865         skinframe->fog = NULL;
5866         skinframe->reflect = NULL;
5867         skinframe->hasalpha = false;
5868
5869         skinframe->avgcolor[0] = rand() / RAND_MAX;
5870         skinframe->avgcolor[1] = rand() / RAND_MAX;
5871         skinframe->avgcolor[2] = rand() / RAND_MAX;
5872         skinframe->avgcolor[3] = 1;
5873
5874         return skinframe;
5875 }
5876
5877 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5878 typedef struct suffixinfo_s
5879 {
5880         char *suffix;
5881         qboolean flipx, flipy, flipdiagonal;
5882 }
5883 suffixinfo_t;
5884 static suffixinfo_t suffix[3][6] =
5885 {
5886         {
5887                 {"px",   false, false, false},
5888                 {"nx",   false, false, false},
5889                 {"py",   false, false, false},
5890                 {"ny",   false, false, false},
5891                 {"pz",   false, false, false},
5892                 {"nz",   false, false, false}
5893         },
5894         {
5895                 {"posx", false, false, false},
5896                 {"negx", false, false, false},
5897                 {"posy", false, false, false},
5898                 {"negy", false, false, false},
5899                 {"posz", false, false, false},
5900                 {"negz", false, false, false}
5901         },
5902         {
5903                 {"rt",    true, false,  true},
5904                 {"lf",   false,  true,  true},
5905                 {"ft",    true,  true, false},
5906                 {"bk",   false, false, false},
5907                 {"up",    true, false,  true},
5908                 {"dn",    true, false,  true}
5909         }
5910 };
5911
5912 static int componentorder[4] = {0, 1, 2, 3};
5913
5914 rtexture_t *R_LoadCubemap(const char *basename)
5915 {
5916         int i, j, cubemapsize;
5917         unsigned char *cubemappixels, *image_buffer;
5918         rtexture_t *cubemaptexture;
5919         char name[256];
5920         // must start 0 so the first loadimagepixels has no requested width/height
5921         cubemapsize = 0;
5922         cubemappixels = NULL;
5923         cubemaptexture = NULL;
5924         // keep trying different suffix groups (posx, px, rt) until one loads
5925         for (j = 0;j < 3 && !cubemappixels;j++)
5926         {
5927                 // load the 6 images in the suffix group
5928                 for (i = 0;i < 6;i++)
5929                 {
5930                         // generate an image name based on the base and and suffix
5931                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5932                         // load it
5933                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
5934                         {
5935                                 // an image loaded, make sure width and height are equal
5936                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
5937                                 {
5938                                         // if this is the first image to load successfully, allocate the cubemap memory
5939                                         if (!cubemappixels && image_width >= 1)
5940                                         {
5941                                                 cubemapsize = image_width;
5942                                                 // note this clears to black, so unavailable sides are black
5943                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
5944                                         }
5945                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
5946                                         if (cubemappixels)
5947                                                 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);
5948                                 }
5949                                 else
5950                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
5951                                 // free the image
5952                                 Mem_Free(image_buffer);
5953                         }
5954                 }
5955         }
5956         // if a cubemap loaded, upload it
5957         if (cubemappixels)
5958         {
5959                 if (developer_loading.integer)
5960                         Con_Printf("loading cubemap \"%s\"\n", basename);
5961
5962                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
5963                 Mem_Free(cubemappixels);
5964         }
5965         else
5966         {
5967                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
5968                 if (developer_loading.integer)
5969                 {
5970                         Con_Printf("(tried tried images ");
5971                         for (j = 0;j < 3;j++)
5972                                 for (i = 0;i < 6;i++)
5973                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
5974                         Con_Print(" and was unable to find any of them).\n");
5975                 }
5976         }
5977         return cubemaptexture;
5978 }
5979
5980 rtexture_t *R_GetCubemap(const char *basename)
5981 {
5982         int i;
5983         for (i = 0;i < r_texture_numcubemaps;i++)
5984                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
5985                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
5986         if (i >= MAX_CUBEMAPS)
5987                 return r_texture_whitecube;
5988         r_texture_numcubemaps++;
5989         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
5990         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
5991         return r_texture_cubemaps[i].texture;
5992 }
5993
5994 void R_FreeCubemaps(void)
5995 {
5996         int i;
5997         for (i = 0;i < r_texture_numcubemaps;i++)
5998         {
5999                 if (developer_loading.integer)
6000                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6001                 if (r_texture_cubemaps[i].texture)
6002                         R_FreeTexture(r_texture_cubemaps[i].texture);
6003         }
6004         r_texture_numcubemaps = 0;
6005 }
6006
6007 void R_Main_FreeViewCache(void)
6008 {
6009         if (r_refdef.viewcache.entityvisible)
6010                 Mem_Free(r_refdef.viewcache.entityvisible);
6011         if (r_refdef.viewcache.world_pvsbits)
6012                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6013         if (r_refdef.viewcache.world_leafvisible)
6014                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6015         if (r_refdef.viewcache.world_surfacevisible)
6016                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6017         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6018 }
6019
6020 void R_Main_ResizeViewCache(void)
6021 {
6022         int numentities = r_refdef.scene.numentities;
6023         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6024         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6025         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6026         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6027         if (r_refdef.viewcache.maxentities < numentities)
6028         {
6029                 r_refdef.viewcache.maxentities = numentities;
6030                 if (r_refdef.viewcache.entityvisible)
6031                         Mem_Free(r_refdef.viewcache.entityvisible);
6032                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6033         }
6034         if (r_refdef.viewcache.world_numclusters != numclusters)
6035         {
6036                 r_refdef.viewcache.world_numclusters = numclusters;
6037                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6038                 if (r_refdef.viewcache.world_pvsbits)
6039                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6040                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6041         }
6042         if (r_refdef.viewcache.world_numleafs != numleafs)
6043         {
6044                 r_refdef.viewcache.world_numleafs = numleafs;
6045                 if (r_refdef.viewcache.world_leafvisible)
6046                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6047                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6048         }
6049         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6050         {
6051                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6052                 if (r_refdef.viewcache.world_surfacevisible)
6053                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6054                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6055         }
6056 }
6057
6058 extern rtexture_t *loadingscreentexture;
6059 void gl_main_start(void)
6060 {
6061         loadingscreentexture = NULL;
6062         r_texture_blanknormalmap = NULL;
6063         r_texture_white = NULL;
6064         r_texture_grey128 = NULL;
6065         r_texture_black = NULL;
6066         r_texture_whitecube = NULL;
6067         r_texture_normalizationcube = NULL;
6068         r_texture_fogattenuation = NULL;
6069         r_texture_gammaramps = NULL;
6070         r_texture_numcubemaps = 0;
6071
6072         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6073         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6074
6075         switch(vid.renderpath)
6076         {
6077         case RENDERPATH_GL20:
6078         case RENDERPATH_CGGL:
6079                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6080                 Cvar_SetValueQuick(&gl_combine, 1);
6081                 Cvar_SetValueQuick(&r_glsl, 1);
6082                 r_loadnormalmap = true;
6083                 r_loadgloss = true;
6084                 r_loadfog = false;
6085                 break;
6086         case RENDERPATH_GL13:
6087                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6088                 Cvar_SetValueQuick(&gl_combine, 1);
6089                 Cvar_SetValueQuick(&r_glsl, 0);
6090                 r_loadnormalmap = false;
6091                 r_loadgloss = false;
6092                 r_loadfog = true;
6093                 break;
6094         case RENDERPATH_GL11:
6095                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6096                 Cvar_SetValueQuick(&gl_combine, 0);
6097                 Cvar_SetValueQuick(&r_glsl, 0);
6098                 r_loadnormalmap = false;
6099                 r_loadgloss = false;
6100                 r_loadfog = true;
6101                 break;
6102         }
6103
6104         R_AnimCache_Free();
6105         R_FrameData_Reset();
6106
6107         r_numqueries = 0;
6108         r_maxqueries = 0;
6109         memset(r_queries, 0, sizeof(r_queries));
6110
6111         r_qwskincache = NULL;
6112         r_qwskincache_size = 0;
6113
6114         // set up r_skinframe loading system for textures
6115         memset(&r_skinframe, 0, sizeof(r_skinframe));
6116         r_skinframe.loadsequence = 1;
6117         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6118
6119         r_main_texturepool = R_AllocTexturePool();
6120         R_BuildBlankTextures();
6121         R_BuildNoTexture();
6122         if (vid.support.arb_texture_cube_map)
6123         {
6124                 R_BuildWhiteCube();
6125                 R_BuildNormalizationCube();
6126         }
6127         r_texture_fogattenuation = NULL;
6128         r_texture_gammaramps = NULL;
6129         //r_texture_fogintensity = NULL;
6130         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6131         memset(&r_waterstate, 0, sizeof(r_waterstate));
6132         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6133         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6134         glslshaderstring = NULL;
6135 #ifdef SUPPORTCG
6136         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6137         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6138         cgshaderstring = NULL;
6139 #endif
6140         memset(&r_svbsp, 0, sizeof (r_svbsp));
6141
6142         r_refdef.fogmasktable_density = 0;
6143 }
6144
6145 void gl_main_shutdown(void)
6146 {
6147         R_AnimCache_Free();
6148         R_FrameData_Reset();
6149
6150         R_Main_FreeViewCache();
6151
6152         if (r_maxqueries)
6153                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6154
6155         r_numqueries = 0;
6156         r_maxqueries = 0;
6157         memset(r_queries, 0, sizeof(r_queries));
6158
6159         r_qwskincache = NULL;
6160         r_qwskincache_size = 0;
6161
6162         // clear out the r_skinframe state
6163         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6164         memset(&r_skinframe, 0, sizeof(r_skinframe));
6165
6166         if (r_svbsp.nodes)
6167                 Mem_Free(r_svbsp.nodes);
6168         memset(&r_svbsp, 0, sizeof (r_svbsp));
6169         R_FreeTexturePool(&r_main_texturepool);
6170         loadingscreentexture = NULL;
6171         r_texture_blanknormalmap = NULL;
6172         r_texture_white = NULL;
6173         r_texture_grey128 = NULL;
6174         r_texture_black = NULL;
6175         r_texture_whitecube = NULL;
6176         r_texture_normalizationcube = NULL;
6177         r_texture_fogattenuation = NULL;
6178         r_texture_gammaramps = NULL;
6179         r_texture_numcubemaps = 0;
6180         //r_texture_fogintensity = NULL;
6181         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6182         memset(&r_waterstate, 0, sizeof(r_waterstate));
6183         R_GLSL_Restart_f();
6184 }
6185
6186 extern void CL_ParseEntityLump(char *entitystring);
6187 void gl_main_newmap(void)
6188 {
6189         // FIXME: move this code to client
6190         int l;
6191         char *entities, entname[MAX_QPATH];
6192         if (r_qwskincache)
6193                 Mem_Free(r_qwskincache);
6194         r_qwskincache = NULL;
6195         r_qwskincache_size = 0;
6196         if (cl.worldmodel)
6197         {
6198                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6199                 l = (int)strlen(entname) - 4;
6200                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6201                 {
6202                         memcpy(entname + l, ".ent", 5);
6203                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6204                         {
6205                                 CL_ParseEntityLump(entities);
6206                                 Mem_Free(entities);
6207                                 return;
6208                         }
6209                 }
6210                 if (cl.worldmodel->brush.entities)
6211                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6212         }
6213         R_Main_FreeViewCache();
6214
6215         R_FrameData_Reset();
6216 }
6217
6218 void GL_Main_Init(void)
6219 {
6220         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6221
6222         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6223         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6224         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6225         if (gamemode == GAME_NEHAHRA)
6226         {
6227                 Cvar_RegisterVariable (&gl_fogenable);
6228                 Cvar_RegisterVariable (&gl_fogdensity);
6229                 Cvar_RegisterVariable (&gl_fogred);
6230                 Cvar_RegisterVariable (&gl_foggreen);
6231                 Cvar_RegisterVariable (&gl_fogblue);
6232                 Cvar_RegisterVariable (&gl_fogstart);
6233                 Cvar_RegisterVariable (&gl_fogend);
6234                 Cvar_RegisterVariable (&gl_skyclip);
6235         }
6236         Cvar_RegisterVariable(&r_motionblur);
6237         Cvar_RegisterVariable(&r_motionblur_maxblur);
6238         Cvar_RegisterVariable(&r_motionblur_bmin);
6239         Cvar_RegisterVariable(&r_motionblur_vmin);
6240         Cvar_RegisterVariable(&r_motionblur_vmax);
6241         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6242         Cvar_RegisterVariable(&r_motionblur_randomize);
6243         Cvar_RegisterVariable(&r_damageblur);
6244         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6245         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6246         Cvar_RegisterVariable(&r_equalize_entities_by);
6247         Cvar_RegisterVariable(&r_equalize_entities_to);
6248         Cvar_RegisterVariable(&r_depthfirst);
6249         Cvar_RegisterVariable(&r_useinfinitefarclip);
6250         Cvar_RegisterVariable(&r_farclip_base);
6251         Cvar_RegisterVariable(&r_farclip_world);
6252         Cvar_RegisterVariable(&r_nearclip);
6253         Cvar_RegisterVariable(&r_showbboxes);
6254         Cvar_RegisterVariable(&r_showsurfaces);
6255         Cvar_RegisterVariable(&r_showtris);
6256         Cvar_RegisterVariable(&r_shownormals);
6257         Cvar_RegisterVariable(&r_showlighting);
6258         Cvar_RegisterVariable(&r_showshadowvolumes);
6259         Cvar_RegisterVariable(&r_showcollisionbrushes);
6260         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6261         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6262         Cvar_RegisterVariable(&r_showdisabledepthtest);
6263         Cvar_RegisterVariable(&r_drawportals);
6264         Cvar_RegisterVariable(&r_drawentities);
6265         Cvar_RegisterVariable(&r_cullentities_trace);
6266         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6267         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6268         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6269         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6270         Cvar_RegisterVariable(&r_drawviewmodel);
6271         Cvar_RegisterVariable(&r_speeds);
6272         Cvar_RegisterVariable(&r_fullbrights);
6273         Cvar_RegisterVariable(&r_wateralpha);
6274         Cvar_RegisterVariable(&r_dynamic);
6275         Cvar_RegisterVariable(&r_fullbright);
6276         Cvar_RegisterVariable(&r_shadows);
6277         Cvar_RegisterVariable(&r_shadows_darken);
6278         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6279         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6280         Cvar_RegisterVariable(&r_shadows_throwdistance);
6281         Cvar_RegisterVariable(&r_shadows_throwdirection);
6282         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6283         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6284         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6285         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6286         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6287         Cvar_RegisterVariable(&r_fog_exp2);
6288         Cvar_RegisterVariable(&r_drawfog);
6289         Cvar_RegisterVariable(&r_transparentdepthmasking);
6290         Cvar_RegisterVariable(&r_texture_dds_load);
6291         Cvar_RegisterVariable(&r_texture_dds_save);
6292         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6293         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6294         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6295         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6296         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6297         Cvar_RegisterVariable(&r_textureunits);
6298         Cvar_RegisterVariable(&gl_combine);
6299         Cvar_RegisterVariable(&r_glsl);
6300         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6301         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6302         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6303         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6304         Cvar_RegisterVariable(&r_glsl_postprocess);
6305         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6309         Cvar_RegisterVariable(&r_water);
6310         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6311         Cvar_RegisterVariable(&r_water_clippingplanebias);
6312         Cvar_RegisterVariable(&r_water_refractdistort);
6313         Cvar_RegisterVariable(&r_water_reflectdistort);
6314         Cvar_RegisterVariable(&r_lerpsprites);
6315         Cvar_RegisterVariable(&r_lerpmodels);
6316         Cvar_RegisterVariable(&r_lerplightstyles);
6317         Cvar_RegisterVariable(&r_waterscroll);
6318         Cvar_RegisterVariable(&r_bloom);
6319         Cvar_RegisterVariable(&r_bloom_colorscale);
6320         Cvar_RegisterVariable(&r_bloom_brighten);
6321         Cvar_RegisterVariable(&r_bloom_blur);
6322         Cvar_RegisterVariable(&r_bloom_resolution);
6323         Cvar_RegisterVariable(&r_bloom_colorexponent);
6324         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6325         Cvar_RegisterVariable(&r_hdr);
6326         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6327         Cvar_RegisterVariable(&r_hdr_glowintensity);
6328         Cvar_RegisterVariable(&r_hdr_range);
6329         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6330         Cvar_RegisterVariable(&developer_texturelogging);
6331         Cvar_RegisterVariable(&gl_lightmaps);
6332         Cvar_RegisterVariable(&r_test);
6333         Cvar_RegisterVariable(&r_batchmode);
6334         Cvar_RegisterVariable(&r_glsl_saturation);
6335         Cvar_RegisterVariable(&r_framedatasize);
6336         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6337                 Cvar_SetValue("r_fullbrights", 0);
6338         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6339
6340         Cvar_RegisterVariable(&r_track_sprites);
6341         Cvar_RegisterVariable(&r_track_sprites_flags);
6342         Cvar_RegisterVariable(&r_track_sprites_scalew);
6343         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6344         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6345         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6346 }
6347
6348 extern void R_Textures_Init(void);
6349 extern void GL_Draw_Init(void);
6350 extern void GL_Main_Init(void);
6351 extern void R_Shadow_Init(void);
6352 extern void R_Sky_Init(void);
6353 extern void GL_Surf_Init(void);
6354 extern void R_Particles_Init(void);
6355 extern void R_Explosion_Init(void);
6356 extern void gl_backend_init(void);
6357 extern void Sbar_Init(void);
6358 extern void R_LightningBeams_Init(void);
6359 extern void Mod_RenderInit(void);
6360 extern void Font_Init(void);
6361
6362 void Render_Init(void)
6363 {
6364         gl_backend_init();
6365         R_Textures_Init();
6366         GL_Main_Init();
6367         Font_Init();
6368         GL_Draw_Init();
6369         R_Shadow_Init();
6370         R_Sky_Init();
6371         GL_Surf_Init();
6372         Sbar_Init();
6373         R_Particles_Init();
6374         R_Explosion_Init();
6375         R_LightningBeams_Init();
6376         Mod_RenderInit();
6377 }
6378
6379 /*
6380 ===============
6381 GL_Init
6382 ===============
6383 */
6384 extern char *ENGINE_EXTENSIONS;
6385 void GL_Init (void)
6386 {
6387         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6388         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6389         gl_version = (const char *)qglGetString(GL_VERSION);
6390         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6391
6392         if (!gl_extensions)
6393                 gl_extensions = "";
6394         if (!gl_platformextensions)
6395                 gl_platformextensions = "";
6396
6397         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6398         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6399         Con_Printf("GL_VERSION: %s\n", gl_version);
6400         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6401         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6402
6403         VID_CheckExtensions();
6404
6405         // LordHavoc: report supported extensions
6406         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6407
6408         // clear to black (loading plaque will be seen over this)
6409         CHECKGLERROR
6410         qglClearColor(0,0,0,1);CHECKGLERROR
6411         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6412 }
6413
6414 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6415 {
6416         int i;
6417         mplane_t *p;
6418         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6419         {
6420                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6421                 if (i == 4)
6422                         continue;
6423                 p = r_refdef.view.frustum + i;
6424                 switch(p->signbits)
6425                 {
6426                 default:
6427                 case 0:
6428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6429                                 return true;
6430                         break;
6431                 case 1:
6432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6433                                 return true;
6434                         break;
6435                 case 2:
6436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6437                                 return true;
6438                         break;
6439                 case 3:
6440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6441                                 return true;
6442                         break;
6443                 case 4:
6444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6445                                 return true;
6446                         break;
6447                 case 5:
6448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6449                                 return true;
6450                         break;
6451                 case 6:
6452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6453                                 return true;
6454                         break;
6455                 case 7:
6456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6457                                 return true;
6458                         break;
6459                 }
6460         }
6461         return false;
6462 }
6463
6464 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6465 {
6466         int i;
6467         const mplane_t *p;
6468         for (i = 0;i < numplanes;i++)
6469         {
6470                 p = planes + i;
6471                 switch(p->signbits)
6472                 {
6473                 default:
6474                 case 0:
6475                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6476                                 return true;
6477                         break;
6478                 case 1:
6479                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6480                                 return true;
6481                         break;
6482                 case 2:
6483                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6484                                 return true;
6485                         break;
6486                 case 3:
6487                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6488                                 return true;
6489                         break;
6490                 case 4:
6491                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6492                                 return true;
6493                         break;
6494                 case 5:
6495                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6496                                 return true;
6497                         break;
6498                 case 6:
6499                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6500                                 return true;
6501                         break;
6502                 case 7:
6503                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6504                                 return true;
6505                         break;
6506                 }
6507         }
6508         return false;
6509 }
6510
6511 //==================================================================================
6512
6513 // LordHavoc: this stores temporary data used within the same frame
6514
6515 qboolean r_framedata_failed;
6516 static size_t r_framedata_size;
6517 static size_t r_framedata_current;
6518 static void *r_framedata_base;
6519
6520 void R_FrameData_Reset(void)
6521 {
6522         if (r_framedata_base)
6523                 Mem_Free(r_framedata_base);
6524         r_framedata_base = NULL;
6525         r_framedata_size = 0;
6526         r_framedata_current = 0;
6527         r_framedata_failed = false;
6528 }
6529
6530 void R_FrameData_NewFrame(void)
6531 {
6532         size_t wantedsize;
6533         if (r_framedata_failed)
6534                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6535         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6536         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6537         if (r_framedata_size != wantedsize)
6538         {
6539                 r_framedata_size = wantedsize;
6540                 if (r_framedata_base)
6541                         Mem_Free(r_framedata_base);
6542                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6543         }
6544         r_framedata_current = 0;
6545         r_framedata_failed = false;
6546 }
6547
6548 void *R_FrameData_Alloc(size_t size)
6549 {
6550         void *data;
6551
6552         // align to 16 byte boundary
6553         size = (size + 15) & ~15;
6554         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6555         r_framedata_current += size;
6556
6557         // check overflow
6558         if (r_framedata_current > r_framedata_size)
6559                 r_framedata_failed = true;
6560
6561         // return NULL on everything after a failure
6562         if (r_framedata_failed)
6563                 return NULL;
6564
6565         return data;
6566 }
6567
6568 void *R_FrameData_Store(size_t size, void *data)
6569 {
6570         void *d = R_FrameData_Alloc(size);
6571         if (d)
6572                 memcpy(d, data, size);
6573         return d;
6574 }
6575
6576 //==================================================================================
6577
6578 // LordHavoc: animcache originally written by Echon, rewritten since then
6579
6580 /**
6581  * Animation cache prevents re-generating mesh data for an animated model
6582  * multiple times in one frame for lighting, shadowing, reflections, etc.
6583  */
6584
6585 void R_AnimCache_Free(void)
6586 {
6587 }
6588
6589 void R_AnimCache_ClearCache(void)
6590 {
6591         int i;
6592         entity_render_t *ent;
6593
6594         for (i = 0;i < r_refdef.scene.numentities;i++)
6595         {
6596                 ent = r_refdef.scene.entities[i];
6597                 ent->animcache_vertex3f = NULL;
6598                 ent->animcache_normal3f = NULL;
6599                 ent->animcache_svector3f = NULL;
6600                 ent->animcache_tvector3f = NULL;
6601         }
6602 }
6603
6604 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6605 {
6606         dp_model_t *model = ent->model;
6607         int numvertices;
6608         // see if it's already cached this frame
6609         if (ent->animcache_vertex3f)
6610         {
6611                 // add normals/tangents if needed
6612                 if (wantnormals || wanttangents)
6613                 {
6614                         if (ent->animcache_normal3f)
6615                                 wantnormals = false;
6616                         if (ent->animcache_svector3f)
6617                                 wanttangents = false;
6618                         if (wantnormals || wanttangents)
6619                         {
6620                                 numvertices = model->surfmesh.num_vertices;
6621                                 if (wantnormals)
6622                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6623                                 if (wanttangents)
6624                                 {
6625                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6626                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6627                                 }
6628                                 if (!r_framedata_failed)
6629                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6630                         }
6631                 }
6632         }
6633         else
6634         {
6635                 // see if this ent is worth caching
6636                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6637                         return false;
6638                 // get some memory for this entity and generate mesh data
6639                 numvertices = model->surfmesh.num_vertices;
6640                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6641                 if (wantnormals)
6642                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6643                 if (wanttangents)
6644                 {
6645                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6646                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6647                 }
6648                 if (!r_framedata_failed)
6649                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6650         }
6651         return !r_framedata_failed;
6652 }
6653
6654 void R_AnimCache_CacheVisibleEntities(void)
6655 {
6656         int i;
6657         qboolean wantnormals = !r_showsurfaces.integer;
6658         qboolean wanttangents = !r_showsurfaces.integer;
6659
6660         switch(vid.renderpath)
6661         {
6662         case RENDERPATH_GL20:
6663         case RENDERPATH_CGGL:
6664                 break;
6665         case RENDERPATH_GL13:
6666         case RENDERPATH_GL11:
6667                 wanttangents = false;
6668                 break;
6669         }
6670
6671         // TODO: thread this
6672         // NOTE: R_PrepareRTLights() also caches entities
6673
6674         for (i = 0;i < r_refdef.scene.numentities;i++)
6675                 if (r_refdef.viewcache.entityvisible[i])
6676                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6677
6678         if (r_shadows.integer)
6679                 for (i = 0;i < r_refdef.scene.numentities;i++)
6680                         if (!r_refdef.viewcache.entityvisible[i])
6681                                 R_AnimCache_GetEntity(r_refdef.scene.entities[i], false, false);
6682 }
6683
6684 //==================================================================================
6685
6686 static void R_View_UpdateEntityLighting (void)
6687 {
6688         int i;
6689         entity_render_t *ent;
6690         vec3_t tempdiffusenormal, avg;
6691         vec_t f, fa, fd, fdd;
6692
6693         for (i = 0;i < r_refdef.scene.numentities;i++)
6694         {
6695                 ent = r_refdef.scene.entities[i];
6696
6697                 // skip unseen models
6698                 if (!r_refdef.viewcache.entityvisible[i] && r_shadows.integer != 1)
6699                         continue;
6700
6701                 // skip bsp models
6702                 if (ent->model && ent->model->brush.num_leafs)
6703                 {
6704                         // TODO: use modellight for r_ambient settings on world?
6705                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6706                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6707                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6708                         continue;
6709                 }
6710
6711                 // fetch the lighting from the worldmodel data
6712                 VectorClear(ent->modellight_ambient);
6713                 VectorClear(ent->modellight_diffuse);
6714                 VectorClear(tempdiffusenormal);
6715                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6716                 {
6717                         vec3_t org;
6718                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6719                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6720                         if(ent->flags & RENDER_EQUALIZE)
6721                         {
6722                                 // first fix up ambient lighting...
6723                                 if(r_equalize_entities_minambient.value > 0)
6724                                 {
6725                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6726                                         if(fd > 0)
6727                                         {
6728                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6729                                                 if(fa < r_equalize_entities_minambient.value * fd)
6730                                                 {
6731                                                         // solve:
6732                                                         //   fa'/fd' = minambient
6733                                                         //   fa'+0.25*fd' = fa+0.25*fd
6734                                                         //   ...
6735                                                         //   fa' = fd' * minambient
6736                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6737                                                         //   ...
6738                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6739                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6740                                                         //   ...
6741                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6742                                                         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
6743                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6744                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6745                                                 }
6746                                         }
6747                                 }
6748
6749                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6750                                 {
6751                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6752                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6753                                         if(f > 0)
6754                                         {
6755                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6756                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6757                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6758                                         }
6759                                 }
6760                         }
6761                 }
6762                 else // highly rare
6763                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6764
6765                 // move the light direction into modelspace coordinates for lighting code
6766                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6767                 if(VectorLength2(ent->modellight_lightdir) == 0)
6768                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6769                 VectorNormalize(ent->modellight_lightdir);
6770         }
6771 }
6772
6773 #define MAX_LINEOFSIGHTTRACES 64
6774
6775 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6776 {
6777         int i;
6778         vec3_t boxmins, boxmaxs;
6779         vec3_t start;
6780         vec3_t end;
6781         dp_model_t *model = r_refdef.scene.worldmodel;
6782
6783         if (!model || !model->brush.TraceLineOfSight)
6784                 return true;
6785
6786         // expand the box a little
6787         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6788         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6789         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6790         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6791         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6792         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6793
6794         // return true if eye is inside enlarged box
6795         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6796                 return true;
6797
6798         // try center
6799         VectorCopy(eye, start);
6800         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6801         if (model->brush.TraceLineOfSight(model, start, end))
6802                 return true;
6803
6804         // try various random positions
6805         for (i = 0;i < numsamples;i++)
6806         {
6807                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6808                 if (model->brush.TraceLineOfSight(model, start, end))
6809                         return true;
6810         }
6811
6812         return false;
6813 }
6814
6815
6816 static void R_View_UpdateEntityVisible (void)
6817 {
6818         int i;
6819         int renderimask;
6820         int samples;
6821         entity_render_t *ent;
6822
6823         renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
6824         if (!r_drawviewmodel.integer)
6825                 renderimask |= RENDER_VIEWMODEL;
6826         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6827         {
6828                 // worldmodel can check visibility
6829                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6830                 for (i = 0;i < r_refdef.scene.numentities;i++)
6831                 {
6832                         ent = r_refdef.scene.entities[i];
6833                         if (!(ent->flags & renderimask))
6834                         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)))
6835                         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))
6836                                 r_refdef.viewcache.entityvisible[i] = true;
6837                 }
6838                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight)
6839                 {
6840                         for (i = 0;i < r_refdef.scene.numentities;i++)
6841                         {
6842                                 ent = r_refdef.scene.entities[i];
6843                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6844                                 {
6845                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6846                                         if (samples < 0)
6847                                                 continue; // temp entities do pvs only
6848                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6849                                                 ent->last_trace_visibility = realtime;
6850                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6851                                                 r_refdef.viewcache.entityvisible[i] = 0;
6852                                 }
6853                         }
6854                 }
6855         }
6856         else
6857         {
6858                 // no worldmodel or it can't check visibility
6859                 for (i = 0;i < r_refdef.scene.numentities;i++)
6860                 {
6861                         ent = r_refdef.scene.entities[i];
6862                         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));
6863                 }
6864         }
6865 }
6866
6867 /// only used if skyrendermasked, and normally returns false
6868 int R_DrawBrushModelsSky (void)
6869 {
6870         int i, sky;
6871         entity_render_t *ent;
6872
6873         sky = false;
6874         for (i = 0;i < r_refdef.scene.numentities;i++)
6875         {
6876                 if (!r_refdef.viewcache.entityvisible[i])
6877                         continue;
6878                 ent = r_refdef.scene.entities[i];
6879                 if (!ent->model || !ent->model->DrawSky)
6880                         continue;
6881                 ent->model->DrawSky(ent);
6882                 sky = true;
6883         }
6884         return sky;
6885 }
6886
6887 static void R_DrawNoModel(entity_render_t *ent);
6888 static void R_DrawModels(void)
6889 {
6890         int i;
6891         entity_render_t *ent;
6892
6893         for (i = 0;i < r_refdef.scene.numentities;i++)
6894         {
6895                 if (!r_refdef.viewcache.entityvisible[i])
6896                         continue;
6897                 ent = r_refdef.scene.entities[i];
6898                 r_refdef.stats.entities++;
6899                 if (ent->model && ent->model->Draw != NULL)
6900                         ent->model->Draw(ent);
6901                 else
6902                         R_DrawNoModel(ent);
6903         }
6904 }
6905
6906 static void R_DrawModelsDepth(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->DrawDepth != NULL)
6917                         ent->model->DrawDepth(ent);
6918         }
6919 }
6920
6921 static void R_DrawModelsDebug(void)
6922 {
6923         int i;
6924         entity_render_t *ent;
6925
6926         for (i = 0;i < r_refdef.scene.numentities;i++)
6927         {
6928                 if (!r_refdef.viewcache.entityvisible[i])
6929                         continue;
6930                 ent = r_refdef.scene.entities[i];
6931                 if (ent->model && ent->model->DrawDebug != NULL)
6932                         ent->model->DrawDebug(ent);
6933         }
6934 }
6935
6936 static void R_DrawModelsAddWaterPlanes(void)
6937 {
6938         int i;
6939         entity_render_t *ent;
6940
6941         for (i = 0;i < r_refdef.scene.numentities;i++)
6942         {
6943                 if (!r_refdef.viewcache.entityvisible[i])
6944                         continue;
6945                 ent = r_refdef.scene.entities[i];
6946                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
6947                         ent->model->DrawAddWaterPlanes(ent);
6948         }
6949 }
6950
6951 static void R_View_SetFrustum(void)
6952 {
6953         int i;
6954         double slopex, slopey;
6955         vec3_t forward, left, up, origin;
6956
6957         // we can't trust r_refdef.view.forward and friends in reflected scenes
6958         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
6959
6960 #if 0
6961         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
6962         r_refdef.view.frustum[0].normal[1] = 0 - 0;
6963         r_refdef.view.frustum[0].normal[2] = -1 - 0;
6964         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
6965         r_refdef.view.frustum[1].normal[1] = 0 + 0;
6966         r_refdef.view.frustum[1].normal[2] = -1 + 0;
6967         r_refdef.view.frustum[2].normal[0] = 0 - 0;
6968         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
6969         r_refdef.view.frustum[2].normal[2] = -1 - 0;
6970         r_refdef.view.frustum[3].normal[0] = 0 + 0;
6971         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
6972         r_refdef.view.frustum[3].normal[2] = -1 + 0;
6973 #endif
6974
6975 #if 0
6976         zNear = r_refdef.nearclip;
6977         nudge = 1.0 - 1.0 / (1<<23);
6978         r_refdef.view.frustum[4].normal[0] = 0 - 0;
6979         r_refdef.view.frustum[4].normal[1] = 0 - 0;
6980         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
6981         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
6982         r_refdef.view.frustum[5].normal[0] = 0 + 0;
6983         r_refdef.view.frustum[5].normal[1] = 0 + 0;
6984         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
6985         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
6986 #endif
6987
6988
6989
6990 #if 0
6991         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
6992         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
6993         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
6994         r_refdef.view.frustum[0].dist = m[15] - m[12];
6995
6996         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
6997         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
6998         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
6999         r_refdef.view.frustum[1].dist = m[15] + m[12];
7000
7001         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7002         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7003         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7004         r_refdef.view.frustum[2].dist = m[15] - m[13];
7005
7006         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7007         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7008         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7009         r_refdef.view.frustum[3].dist = m[15] + m[13];
7010
7011         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7012         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7013         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7014         r_refdef.view.frustum[4].dist = m[15] - m[14];
7015
7016         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7017         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7018         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7019         r_refdef.view.frustum[5].dist = m[15] + m[14];
7020 #endif
7021
7022         if (r_refdef.view.useperspective)
7023         {
7024                 slopex = 1.0 / r_refdef.view.frustum_x;
7025                 slopey = 1.0 / r_refdef.view.frustum_y;
7026                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7027                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7028                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7029                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7030                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7031
7032                 // Leaving those out was a mistake, those were in the old code, and they
7033                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7034                 // I couldn't reproduce it after adding those normalizations. --blub
7035                 VectorNormalize(r_refdef.view.frustum[0].normal);
7036                 VectorNormalize(r_refdef.view.frustum[1].normal);
7037                 VectorNormalize(r_refdef.view.frustum[2].normal);
7038                 VectorNormalize(r_refdef.view.frustum[3].normal);
7039
7040                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7041                 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]);
7042                 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]);
7043                 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]);
7044                 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]);
7045
7046                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7047                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7048                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7049                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7050                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7051         }
7052         else
7053         {
7054                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7055                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7056                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7057                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7058                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7059                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7060                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7061                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7062                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7063                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7064         }
7065         r_refdef.view.numfrustumplanes = 5;
7066
7067         if (r_refdef.view.useclipplane)
7068         {
7069                 r_refdef.view.numfrustumplanes = 6;
7070                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7071         }
7072
7073         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7074                 PlaneClassify(r_refdef.view.frustum + i);
7075
7076         // LordHavoc: note to all quake engine coders, Quake had a special case
7077         // for 90 degrees which assumed a square view (wrong), so I removed it,
7078         // Quake2 has it disabled as well.
7079
7080         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7081         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7082         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7083         //PlaneClassify(&frustum[0]);
7084
7085         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7086         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7087         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7088         //PlaneClassify(&frustum[1]);
7089
7090         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7091         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7092         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7093         //PlaneClassify(&frustum[2]);
7094
7095         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7096         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7097         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7098         //PlaneClassify(&frustum[3]);
7099
7100         // nearclip plane
7101         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7102         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7103         //PlaneClassify(&frustum[4]);
7104 }
7105
7106 void R_View_Update(void)
7107 {
7108         R_Main_ResizeViewCache();
7109         R_View_SetFrustum();
7110         R_View_WorldVisibility(r_refdef.view.useclipplane);
7111         R_View_UpdateEntityVisible();
7112         R_View_UpdateEntityLighting();
7113 }
7114
7115 void R_SetupView(qboolean allowwaterclippingplane)
7116 {
7117         const float *customclipplane = NULL;
7118         float plane[4];
7119         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7120         {
7121                 // LordHavoc: couldn't figure out how to make this approach the
7122                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7123                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7124                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7125                         dist = r_refdef.view.clipplane.dist;
7126                 plane[0] = r_refdef.view.clipplane.normal[0];
7127                 plane[1] = r_refdef.view.clipplane.normal[1];
7128                 plane[2] = r_refdef.view.clipplane.normal[2];
7129                 plane[3] = dist;
7130                 customclipplane = plane;
7131         }
7132
7133         if (!r_refdef.view.useperspective)
7134                 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);
7135         else if (vid.stencil && r_useinfinitefarclip.integer)
7136                 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);
7137         else
7138                 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);
7139         R_SetViewport(&r_refdef.view.viewport);
7140 }
7141
7142 void R_EntityMatrix(const matrix4x4_t *matrix)
7143 {
7144         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7145         {
7146                 gl_modelmatrixchanged = false;
7147                 gl_modelmatrix = *matrix;
7148                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7149                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7150                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7151                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7152                 CHECKGLERROR
7153                 switch(vid.renderpath)
7154                 {
7155                 case RENDERPATH_GL20:
7156                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7157                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7158                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7159                         break;
7160                 case RENDERPATH_CGGL:
7161 #ifdef SUPPORTCG
7162                         CHECKCGERROR
7163                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7164                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7165                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7166 #endif
7167                         break;
7168                 case RENDERPATH_GL13:
7169                 case RENDERPATH_GL11:
7170                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7171                         break;
7172                 }
7173         }
7174 }
7175
7176 void R_ResetViewRendering2D(void)
7177 {
7178         r_viewport_t viewport;
7179         DrawQ_Finish();
7180
7181         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7182         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);
7183         R_SetViewport(&viewport);
7184         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7185         GL_Color(1, 1, 1, 1);
7186         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7187         GL_BlendFunc(GL_ONE, GL_ZERO);
7188         GL_AlphaTest(false);
7189         GL_ScissorTest(false);
7190         GL_DepthMask(false);
7191         GL_DepthRange(0, 1);
7192         GL_DepthTest(false);
7193         R_EntityMatrix(&identitymatrix);
7194         R_Mesh_ResetTextureState();
7195         GL_PolygonOffset(0, 0);
7196         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7197         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7198         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7199         qglStencilMask(~0);CHECKGLERROR
7200         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7201         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7202         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7203 }
7204
7205 void R_ResetViewRendering3D(void)
7206 {
7207         DrawQ_Finish();
7208
7209         R_SetupView(true);
7210         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7211         GL_Color(1, 1, 1, 1);
7212         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7213         GL_BlendFunc(GL_ONE, GL_ZERO);
7214         GL_AlphaTest(false);
7215         GL_ScissorTest(true);
7216         GL_DepthMask(true);
7217         GL_DepthRange(0, 1);
7218         GL_DepthTest(true);
7219         R_EntityMatrix(&identitymatrix);
7220         R_Mesh_ResetTextureState();
7221         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7222         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7223         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7224         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7225         qglStencilMask(~0);CHECKGLERROR
7226         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7227         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7228         GL_CullFace(r_refdef.view.cullface_back);
7229 }
7230
7231 void R_RenderScene(void);
7232 void R_RenderWaterPlanes(void);
7233
7234 static void R_Water_StartFrame(void)
7235 {
7236         int i;
7237         int waterwidth, waterheight, texturewidth, textureheight;
7238         r_waterstate_waterplane_t *p;
7239
7240         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7241                 return;
7242
7243         switch(vid.renderpath)
7244         {
7245         case RENDERPATH_GL20:
7246         case RENDERPATH_CGGL:
7247                 break;
7248         case RENDERPATH_GL13:
7249         case RENDERPATH_GL11:
7250                 return;
7251         }
7252
7253         // set waterwidth and waterheight to the water resolution that will be
7254         // used (often less than the screen resolution for faster rendering)
7255         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7256         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7257
7258         // calculate desired texture sizes
7259         // can't use water if the card does not support the texture size
7260         if (!r_water.integer || r_showsurfaces.integer)
7261                 texturewidth = textureheight = waterwidth = waterheight = 0;
7262         else if (vid.support.arb_texture_non_power_of_two)
7263         {
7264                 texturewidth = waterwidth;
7265                 textureheight = waterheight;
7266         }
7267         else
7268         {
7269                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7270                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7271         }
7272
7273         // allocate textures as needed
7274         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight)
7275         {
7276                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7277                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7278                 {
7279                         if (p->texture_refraction)
7280                                 R_FreeTexture(p->texture_refraction);
7281                         p->texture_refraction = NULL;
7282                         if (p->texture_reflection)
7283                                 R_FreeTexture(p->texture_reflection);
7284                         p->texture_reflection = NULL;
7285                 }
7286                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7287                 r_waterstate.texturewidth = texturewidth;
7288                 r_waterstate.textureheight = textureheight;
7289         }
7290
7291         if (r_waterstate.texturewidth)
7292         {
7293                 r_waterstate.enabled = true;
7294
7295                 // when doing a reduced render (HDR) we want to use a smaller area
7296                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7297                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7298
7299                 // set up variables that will be used in shader setup
7300                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7301                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7302                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7303                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7304         }
7305
7306         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7307         r_waterstate.numwaterplanes = 0;
7308 }
7309
7310 void R_Water_AddWaterPlane(msurface_t *surface)
7311 {
7312         int triangleindex, planeindex;
7313         const int *e;
7314         vec3_t vert[3];
7315         vec3_t normal;
7316         vec3_t center;
7317         mplane_t plane;
7318         r_waterstate_waterplane_t *p;
7319         texture_t *t = R_GetCurrentTexture(surface->texture);
7320         // just use the first triangle with a valid normal for any decisions
7321         VectorClear(normal);
7322         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7323         {
7324                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7325                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7326                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7327                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7328                 if (VectorLength2(normal) >= 0.001)
7329                         break;
7330         }
7331
7332         VectorCopy(normal, plane.normal);
7333         VectorNormalize(plane.normal);
7334         plane.dist = DotProduct(vert[0], plane.normal);
7335         PlaneClassify(&plane);
7336         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7337         {
7338                 // skip backfaces (except if nocullface is set)
7339                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7340                         return;
7341                 VectorNegate(plane.normal, plane.normal);
7342                 plane.dist *= -1;
7343                 PlaneClassify(&plane);
7344         }
7345
7346
7347         // find a matching plane if there is one
7348         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7349                 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7350                         break;
7351         if (planeindex >= r_waterstate.maxwaterplanes)
7352                 return; // nothing we can do, out of planes
7353
7354         // if this triangle does not fit any known plane rendered this frame, add one
7355         if (planeindex >= r_waterstate.numwaterplanes)
7356         {
7357                 // store the new plane
7358                 r_waterstate.numwaterplanes++;
7359                 p->plane = plane;
7360                 // clear materialflags and pvs
7361                 p->materialflags = 0;
7362                 p->pvsvalid = false;
7363         }
7364         // merge this surface's materialflags into the waterplane
7365         p->materialflags |= t->currentmaterialflags;
7366         // merge this surface's PVS into the waterplane
7367         VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7368         if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7369          && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7370         {
7371                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7372                 p->pvsvalid = true;
7373         }
7374 }
7375
7376 static void R_Water_ProcessPlanes(void)
7377 {
7378         r_refdef_view_t originalview;
7379         r_refdef_view_t myview;
7380         int planeindex;
7381         r_waterstate_waterplane_t *p;
7382
7383         originalview = r_refdef.view;
7384
7385         // make sure enough textures are allocated
7386         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7387         {
7388                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7389                 {
7390                         if (!p->texture_refraction)
7391                                 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);
7392                         if (!p->texture_refraction)
7393                                 goto error;
7394                 }
7395
7396                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7397                 {
7398                         if (!p->texture_reflection)
7399                                 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);
7400                         if (!p->texture_reflection)
7401                                 goto error;
7402                 }
7403         }
7404
7405         // render views
7406         r_refdef.view = originalview;
7407         r_refdef.view.showdebug = false;
7408         r_refdef.view.width = r_waterstate.waterwidth;
7409         r_refdef.view.height = r_waterstate.waterheight;
7410         r_refdef.view.useclipplane = true;
7411         myview = r_refdef.view;
7412         r_waterstate.renderingscene = true;
7413         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7414         {
7415                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7416                 {
7417                         r_refdef.view = myview;
7418                         // render reflected scene and copy into texture
7419                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7420                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7421                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7422                         r_refdef.view.clipplane = p->plane;
7423                         // reverse the cullface settings for this render
7424                         r_refdef.view.cullface_front = GL_FRONT;
7425                         r_refdef.view.cullface_back = GL_BACK;
7426                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7427                         {
7428                                 r_refdef.view.usecustompvs = true;
7429                                 if (p->pvsvalid)
7430                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7431                                 else
7432                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7433                         }
7434
7435                         R_ResetViewRendering3D();
7436                         R_ClearScreen(r_refdef.fogenabled);
7437                         R_View_Update();
7438                         R_RenderScene();
7439
7440                         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);
7441                 }
7442
7443                 // render the normal view scene and copy into texture
7444                 // (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)
7445                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7446                 {
7447                         r_refdef.view = myview;
7448                         r_refdef.view.clipplane = p->plane;
7449                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7450                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7451                         PlaneClassify(&r_refdef.view.clipplane);
7452
7453                         R_ResetViewRendering3D();
7454                         R_ClearScreen(r_refdef.fogenabled);
7455                         R_View_Update();
7456                         R_RenderScene();
7457
7458                         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);
7459                 }
7460
7461         }
7462         r_waterstate.renderingscene = false;
7463         r_refdef.view = originalview;
7464         R_ResetViewRendering3D();
7465         R_ClearScreen(r_refdef.fogenabled);
7466         R_View_Update();
7467         return;
7468 error:
7469         r_refdef.view = originalview;
7470         r_waterstate.renderingscene = false;
7471         Cvar_SetValueQuick(&r_water, 0);
7472         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7473         return;
7474 }
7475
7476 void R_Bloom_StartFrame(void)
7477 {
7478         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7479
7480         switch(vid.renderpath)
7481         {
7482         case RENDERPATH_GL20:
7483         case RENDERPATH_CGGL:
7484                 break;
7485         case RENDERPATH_GL13:
7486         case RENDERPATH_GL11:
7487                 return;
7488         }
7489
7490         // set bloomwidth and bloomheight to the bloom resolution that will be
7491         // used (often less than the screen resolution for faster rendering)
7492         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7493         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7494         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7495         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7496         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7497
7498         // calculate desired texture sizes
7499         if (vid.support.arb_texture_non_power_of_two)
7500         {
7501                 screentexturewidth = r_refdef.view.width;
7502                 screentextureheight = r_refdef.view.height;
7503                 bloomtexturewidth = r_bloomstate.bloomwidth;
7504                 bloomtextureheight = r_bloomstate.bloomheight;
7505         }
7506         else
7507         {
7508                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7509                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7510                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7511                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7512         }
7513
7514         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))
7515         {
7516                 Cvar_SetValueQuick(&r_hdr, 0);
7517                 Cvar_SetValueQuick(&r_bloom, 0);
7518                 Cvar_SetValueQuick(&r_motionblur, 0);
7519                 Cvar_SetValueQuick(&r_damageblur, 0);
7520         }
7521
7522         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)))
7523                 screentexturewidth = screentextureheight = 0;
7524         if (!r_hdr.integer && !r_bloom.integer)
7525                 bloomtexturewidth = bloomtextureheight = 0;
7526
7527         // allocate textures as needed
7528         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7529         {
7530                 if (r_bloomstate.texture_screen)
7531                         R_FreeTexture(r_bloomstate.texture_screen);
7532                 r_bloomstate.texture_screen = NULL;
7533                 r_bloomstate.screentexturewidth = screentexturewidth;
7534                 r_bloomstate.screentextureheight = screentextureheight;
7535                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7536                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7537         }
7538         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7539         {
7540                 if (r_bloomstate.texture_bloom)
7541                         R_FreeTexture(r_bloomstate.texture_bloom);
7542                 r_bloomstate.texture_bloom = NULL;
7543                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7544                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7545                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7546                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7547         }
7548
7549         // when doing a reduced render (HDR) we want to use a smaller area
7550         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7551         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7552         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7553         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7554         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7555
7556         // set up a texcoord array for the full resolution screen image
7557         // (we have to keep this around to copy back during final render)
7558         r_bloomstate.screentexcoord2f[0] = 0;
7559         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7560         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7561         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7562         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7563         r_bloomstate.screentexcoord2f[5] = 0;
7564         r_bloomstate.screentexcoord2f[6] = 0;
7565         r_bloomstate.screentexcoord2f[7] = 0;
7566
7567         // set up a texcoord array for the reduced resolution bloom image
7568         // (which will be additive blended over the screen image)
7569         r_bloomstate.bloomtexcoord2f[0] = 0;
7570         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7571         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7572         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7573         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7574         r_bloomstate.bloomtexcoord2f[5] = 0;
7575         r_bloomstate.bloomtexcoord2f[6] = 0;
7576         r_bloomstate.bloomtexcoord2f[7] = 0;
7577
7578         if (r_hdr.integer || r_bloom.integer)
7579         {
7580                 r_bloomstate.enabled = true;
7581                 r_bloomstate.hdr = r_hdr.integer != 0;
7582         }
7583
7584         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);
7585 }
7586
7587 void R_Bloom_CopyBloomTexture(float colorscale)
7588 {
7589         r_refdef.stats.bloom++;
7590
7591         // scale down screen texture to the bloom texture size
7592         CHECKGLERROR
7593         R_SetViewport(&r_bloomstate.viewport);
7594         GL_BlendFunc(GL_ONE, GL_ZERO);
7595         GL_Color(colorscale, colorscale, colorscale, 1);
7596         // TODO: optimize with multitexture or GLSL
7597         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7598         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7599         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7600         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7601
7602         // we now have a bloom image in the framebuffer
7603         // copy it into the bloom image texture for later processing
7604         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);
7605         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7606 }
7607
7608 void R_Bloom_CopyHDRTexture(void)
7609 {
7610         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);
7611         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7612 }
7613
7614 void R_Bloom_MakeTexture(void)
7615 {
7616         int x, range, dir;
7617         float xoffset, yoffset, r, brighten;
7618
7619         r_refdef.stats.bloom++;
7620
7621         R_ResetViewRendering2D();
7622         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7623         R_Mesh_ColorPointer(NULL, 0, 0);
7624
7625         // we have a bloom image in the framebuffer
7626         CHECKGLERROR
7627         R_SetViewport(&r_bloomstate.viewport);
7628
7629         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7630         {
7631                 x *= 2;
7632                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7633                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7634                 GL_Color(r, r, r, 1);
7635                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7636                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7637                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7638                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7639
7640                 // copy the vertically blurred bloom view to a texture
7641                 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);
7642                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7643         }
7644
7645         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7646         brighten = r_bloom_brighten.value;
7647         if (r_hdr.integer)
7648                 brighten *= r_hdr_range.value;
7649         brighten = sqrt(brighten);
7650         if(range >= 1)
7651                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7652         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7653         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.offsettexcoord2f, 0, 0);
7654
7655         for (dir = 0;dir < 2;dir++)
7656         {
7657                 // blend on at multiple vertical offsets to achieve a vertical blur
7658                 // TODO: do offset blends using GLSL
7659                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7660                 GL_BlendFunc(GL_ONE, GL_ZERO);
7661                 for (x = -range;x <= range;x++)
7662                 {
7663                         if (!dir){xoffset = 0;yoffset = x;}
7664                         else {xoffset = x;yoffset = 0;}
7665                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7666                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7667                         // compute a texcoord array with the specified x and y offset
7668                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7669                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7670                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7671                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7672                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7673                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7674                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7675                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7676                         // this r value looks like a 'dot' particle, fading sharply to
7677                         // black at the edges
7678                         // (probably not realistic but looks good enough)
7679                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7680                         //r = brighten/(range*2+1);
7681                         r = brighten / (range * 2 + 1);
7682                         if(range >= 1)
7683                                 r *= (1 - x*x/(float)(range*range));
7684                         GL_Color(r, r, r, 1);
7685                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7686                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7687                         GL_BlendFunc(GL_ONE, GL_ONE);
7688                 }
7689
7690                 // copy the vertically blurred bloom view to a texture
7691                 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);
7692                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7693         }
7694
7695         // apply subtract last
7696         // (just like it would be in a GLSL shader)
7697         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7698         {
7699                 GL_BlendFunc(GL_ONE, GL_ZERO);
7700                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7701                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7702                 GL_Color(1, 1, 1, 1);
7703                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7704                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7705
7706                 GL_BlendFunc(GL_ONE, GL_ONE);
7707                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7708                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7709                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7710                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7711                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7712                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7713                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7714
7715                 // copy the darkened bloom view to a texture
7716                 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);
7717                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7718         }
7719 }
7720
7721 void R_HDR_RenderBloomTexture(void)
7722 {
7723         int oldwidth, oldheight;
7724         float oldcolorscale;
7725
7726         oldcolorscale = r_refdef.view.colorscale;
7727         oldwidth = r_refdef.view.width;
7728         oldheight = r_refdef.view.height;
7729         r_refdef.view.width = r_bloomstate.bloomwidth;
7730         r_refdef.view.height = r_bloomstate.bloomheight;
7731
7732         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7733         // TODO: add exposure compensation features
7734         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7735
7736         r_refdef.view.showdebug = false;
7737         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7738
7739         R_ResetViewRendering3D();
7740
7741         R_ClearScreen(r_refdef.fogenabled);
7742         if (r_timereport_active)
7743                 R_TimeReport("HDRclear");
7744
7745         R_View_Update();
7746         if (r_timereport_active)
7747                 R_TimeReport("visibility");
7748
7749         // only do secondary renders with HDR if r_hdr is 2 or higher
7750         r_waterstate.numwaterplanes = 0;
7751         if (r_waterstate.enabled && r_hdr.integer >= 2)
7752                 R_RenderWaterPlanes();
7753
7754         r_refdef.view.showdebug = true;
7755         R_RenderScene();
7756         r_waterstate.numwaterplanes = 0;
7757
7758         R_ResetViewRendering2D();
7759
7760         R_Bloom_CopyHDRTexture();
7761         R_Bloom_MakeTexture();
7762
7763         // restore the view settings
7764         r_refdef.view.width = oldwidth;
7765         r_refdef.view.height = oldheight;
7766         r_refdef.view.colorscale = oldcolorscale;
7767
7768         R_ResetViewRendering3D();
7769
7770         R_ClearScreen(r_refdef.fogenabled);
7771         if (r_timereport_active)
7772                 R_TimeReport("viewclear");
7773 }
7774
7775 static void R_BlendView(void)
7776 {
7777         unsigned int permutation;
7778         float uservecs[4][4];
7779
7780         switch (vid.renderpath)
7781         {
7782         case RENDERPATH_GL20:
7783         case RENDERPATH_CGGL:
7784                 permutation =
7785                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
7786                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
7787                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
7788                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
7789                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
7790
7791                 if (r_bloomstate.texture_screen)
7792                 {
7793                         // make sure the buffer is available
7794                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
7795
7796                         R_ResetViewRendering2D();
7797                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7798                         R_Mesh_ColorPointer(NULL, 0, 0);
7799
7800                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
7801                         {
7802                                 // declare variables
7803                                 float speed;
7804                                 static float avgspeed;
7805
7806                                 speed = VectorLength(cl.movement_velocity);
7807
7808                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
7809                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
7810
7811                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
7812                                 speed = bound(0, speed, 1);
7813                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
7814
7815                                 // calculate values into a standard alpha
7816                                 cl.motionbluralpha = 1 - exp(-
7817                                                 (
7818                                                  (r_motionblur.value * speed / 80)
7819                                                  +
7820                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
7821                                                 )
7822                                                 /
7823                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
7824                                            );
7825
7826                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
7827                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
7828                                 // apply the blur
7829                                 if (cl.motionbluralpha > 0)
7830                                 {
7831                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7832                                         GL_Color(1, 1, 1, cl.motionbluralpha);
7833                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7834                                         R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7835                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7836                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7837                                 }
7838                         }
7839
7840                         // copy view into the screen texture
7841                         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);
7842                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7843                 }
7844                 else if (!r_bloomstate.texture_bloom)
7845                 {
7846                         // we may still have to do view tint...
7847                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7848                         {
7849                                 // apply a color tint to the whole view
7850                                 R_ResetViewRendering2D();
7851                                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7852                                 R_Mesh_ColorPointer(NULL, 0, 0);
7853                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7854                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7855                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7856                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7857                         }
7858                         break; // no screen processing, no bloom, skip it
7859                 }
7860
7861                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
7862                 {
7863                         // render simple bloom effect
7864                         // copy the screen and shrink it and darken it for the bloom process
7865                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
7866                         // make the bloom texture
7867                         R_Bloom_MakeTexture();
7868                 }
7869
7870 #if _MSC_VER >= 1400
7871 #define sscanf sscanf_s
7872 #endif
7873                 memset(uservecs, 0, sizeof(uservecs));
7874                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7875                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7876                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7877                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7878
7879                 R_ResetViewRendering2D();
7880                 R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7881                 R_Mesh_ColorPointer(NULL, 0, 0);
7882                 GL_Color(1, 1, 1, 1);
7883                 GL_BlendFunc(GL_ONE, GL_ZERO);
7884                 R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f, 0, 0);
7885                 R_Mesh_TexCoordPointer(1, 2, r_bloomstate.bloomtexcoord2f, 0, 0);
7886
7887                 switch(vid.renderpath)
7888                 {
7889                 case RENDERPATH_GL20:
7890                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7891                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
7892                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
7893                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
7894                         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]);
7895                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
7896                         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]);
7897                         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]);
7898                         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]);
7899                         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]);
7900                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
7901                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7902                         break;
7903                 case RENDERPATH_CGGL:
7904 #ifdef SUPPORTCG
7905                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
7906                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
7907                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
7908                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
7909                         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
7910                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
7911                         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
7912                         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
7913                         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
7914                         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
7915                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
7916                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
7917 #endif
7918                         break;
7919                 default:
7920                         break;
7921                 }
7922                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7923                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7924                 break;
7925         case RENDERPATH_GL13:
7926         case RENDERPATH_GL11:
7927                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7928                 {
7929                         // apply a color tint to the whole view
7930                         R_ResetViewRendering2D();
7931                         R_Mesh_VertexPointer(r_screenvertex3f, 0, 0);
7932                         R_Mesh_ColorPointer(NULL, 0, 0);
7933                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7934                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7935                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7936                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, polygonelement3s, 0, 0);
7937                 }
7938                 break;
7939         }
7940 }
7941
7942 matrix4x4_t r_waterscrollmatrix;
7943
7944 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
7945 {
7946         if (r_refdef.fog_density)
7947         {
7948                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7949                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7950                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7951
7952                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7953                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7954                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7955                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7956
7957                 {
7958                         vec3_t fogvec;
7959                         VectorCopy(r_refdef.fogcolor, fogvec);
7960                         //   color.rgb *= ContrastBoost * SceneBrightness;
7961                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7962                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7963                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7964                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7965                 }
7966         }
7967 }
7968
7969 void R_UpdateVariables(void)
7970 {
7971         R_Textures_Frame();
7972
7973         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7974
7975         r_refdef.farclip = r_farclip_base.value;
7976         if (r_refdef.scene.worldmodel)
7977                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7978         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7979
7980         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7981                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7982         r_refdef.polygonfactor = 0;
7983         r_refdef.polygonoffset = 0;
7984         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7985         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7986
7987         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7988         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7989         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
7990         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7991         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7992         if (r_showsurfaces.integer)
7993         {
7994                 r_refdef.scene.rtworld = false;
7995                 r_refdef.scene.rtworldshadows = false;
7996                 r_refdef.scene.rtdlight = false;
7997                 r_refdef.scene.rtdlightshadows = false;
7998                 r_refdef.lightmapintensity = 0;
7999         }
8000
8001         if (gamemode == GAME_NEHAHRA)
8002         {
8003                 if (gl_fogenable.integer)
8004                 {
8005                         r_refdef.oldgl_fogenable = true;
8006                         r_refdef.fog_density = gl_fogdensity.value;
8007                         r_refdef.fog_red = gl_fogred.value;
8008                         r_refdef.fog_green = gl_foggreen.value;
8009                         r_refdef.fog_blue = gl_fogblue.value;
8010                         r_refdef.fog_alpha = 1;
8011                         r_refdef.fog_start = 0;
8012                         r_refdef.fog_end = gl_skyclip.value;
8013                         r_refdef.fog_height = 1<<30;
8014                         r_refdef.fog_fadedepth = 128;
8015                 }
8016                 else if (r_refdef.oldgl_fogenable)
8017                 {
8018                         r_refdef.oldgl_fogenable = false;
8019                         r_refdef.fog_density = 0;
8020                         r_refdef.fog_red = 0;
8021                         r_refdef.fog_green = 0;
8022                         r_refdef.fog_blue = 0;
8023                         r_refdef.fog_alpha = 0;
8024                         r_refdef.fog_start = 0;
8025                         r_refdef.fog_end = 0;
8026                         r_refdef.fog_height = 1<<30;
8027                         r_refdef.fog_fadedepth = 128;
8028                 }
8029         }
8030
8031         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8032         r_refdef.fog_start = max(0, r_refdef.fog_start);
8033         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8034
8035         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8036
8037         if (r_refdef.fog_density && r_drawfog.integer)
8038         {
8039                 r_refdef.fogenabled = true;
8040                 // this is the point where the fog reaches 0.9986 alpha, which we
8041                 // consider a good enough cutoff point for the texture
8042                 // (0.9986 * 256 == 255.6)
8043                 if (r_fog_exp2.integer)
8044                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8045                 else
8046                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8047                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8048                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8049                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8050                 // fog color was already set
8051                 // update the fog texture
8052                 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)
8053                         R_BuildFogTexture();
8054         }
8055         else
8056                 r_refdef.fogenabled = false;
8057
8058         switch(vid.renderpath)
8059         {
8060         case RENDERPATH_GL20:
8061         case RENDERPATH_CGGL:
8062                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8063                 {
8064                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8065                         {
8066                                 // build GLSL gamma texture
8067 #define RAMPWIDTH 256
8068                                 unsigned short ramp[RAMPWIDTH * 3];
8069                                 unsigned char rampbgr[RAMPWIDTH][4];
8070                                 int i;
8071
8072                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8073
8074                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8075                                 for(i = 0; i < RAMPWIDTH; ++i)
8076                                 {
8077                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8078                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8079                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8080                                         rampbgr[i][3] = 0;
8081                                 }
8082                                 if (r_texture_gammaramps)
8083                                 {
8084                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8085                                 }
8086                                 else
8087                                 {
8088                                         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);
8089                                 }
8090                         }
8091                 }
8092                 else
8093                 {
8094                         // remove GLSL gamma texture
8095                 }
8096                 break;
8097         case RENDERPATH_GL13:
8098         case RENDERPATH_GL11:
8099                 break;
8100         }
8101 }
8102
8103 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8104 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8105 /*
8106 ================
8107 R_SelectScene
8108 ================
8109 */
8110 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8111         if( scenetype != r_currentscenetype ) {
8112                 // store the old scenetype
8113                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8114                 r_currentscenetype = scenetype;
8115                 // move in the new scene
8116                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8117         }
8118 }
8119
8120 /*
8121 ================
8122 R_GetScenePointer
8123 ================
8124 */
8125 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8126 {
8127         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8128         if( scenetype == r_currentscenetype ) {
8129                 return &r_refdef.scene;
8130         } else {
8131                 return &r_scenes_store[ scenetype ];
8132         }
8133 }
8134
8135 /*
8136 ================
8137 R_RenderView
8138 ================
8139 */
8140 void R_RenderView(void)
8141 {
8142         if (r_timereport_active)
8143                 R_TimeReport("start");
8144         r_textureframe++; // used only by R_GetCurrentTexture
8145         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8146
8147         if (!r_drawentities.integer)
8148                 r_refdef.scene.numentities = 0;
8149
8150         R_AnimCache_ClearCache();
8151         R_FrameData_NewFrame();
8152
8153         if (r_refdef.view.isoverlay)
8154         {
8155                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8156                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8157                 R_TimeReport("depthclear");
8158
8159                 r_refdef.view.showdebug = false;
8160
8161                 r_waterstate.enabled = false;
8162                 r_waterstate.numwaterplanes = 0;
8163
8164                 R_RenderScene();
8165
8166                 CHECKGLERROR
8167                 return;
8168         }
8169
8170         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer/* || !r_refdef.scene.worldmodel*/)
8171                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8172
8173         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8174
8175         // break apart the view matrix into vectors for various purposes
8176         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8177         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8178         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8179         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8180         // make an inverted copy of the view matrix for tracking sprites
8181         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8182
8183         R_Shadow_UpdateWorldLightSelection();
8184
8185         R_Bloom_StartFrame();
8186         R_Water_StartFrame();
8187
8188         CHECKGLERROR
8189         if (r_timereport_active)
8190                 R_TimeReport("viewsetup");
8191
8192         R_ResetViewRendering3D();
8193
8194         if (r_refdef.view.clear || r_refdef.fogenabled)
8195         {
8196                 R_ClearScreen(r_refdef.fogenabled);
8197                 if (r_timereport_active)
8198                         R_TimeReport("viewclear");
8199         }
8200         r_refdef.view.clear = true;
8201
8202         // this produces a bloom texture to be used in R_BlendView() later
8203         if (r_hdr.integer && r_bloomstate.bloomwidth)
8204         {
8205                 R_HDR_RenderBloomTexture();
8206                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8207                 r_textureframe++; // used only by R_GetCurrentTexture
8208         }
8209
8210         r_refdef.view.showdebug = true;
8211
8212         R_View_Update();
8213         if (r_timereport_active)
8214                 R_TimeReport("visibility");
8215
8216         r_waterstate.numwaterplanes = 0;
8217         if (r_waterstate.enabled)
8218                 R_RenderWaterPlanes();
8219
8220         R_RenderScene();
8221         r_waterstate.numwaterplanes = 0;
8222
8223         R_BlendView();
8224         if (r_timereport_active)
8225                 R_TimeReport("blendview");
8226
8227         GL_Scissor(0, 0, vid.width, vid.height);
8228         GL_ScissorTest(false);
8229         CHECKGLERROR
8230 }
8231
8232 void R_RenderWaterPlanes(void)
8233 {
8234         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8235         {
8236                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8237                 if (r_timereport_active)
8238                         R_TimeReport("waterworld");
8239         }
8240
8241         // don't let sound skip if going slow
8242         if (r_refdef.scene.extraupdate)
8243                 S_ExtraUpdate ();
8244
8245         R_DrawModelsAddWaterPlanes();
8246         if (r_timereport_active)
8247                 R_TimeReport("watermodels");
8248
8249         if (r_waterstate.numwaterplanes)
8250         {
8251                 R_Water_ProcessPlanes();
8252                 if (r_timereport_active)
8253                         R_TimeReport("waterscenes");
8254         }
8255 }
8256
8257 extern void R_DrawLightningBeams (void);
8258 extern void VM_CL_AddPolygonsToMeshQueue (void);
8259 extern void R_DrawPortals (void);
8260 extern cvar_t cl_locs_show;
8261 static void R_DrawLocs(void);
8262 static void R_DrawEntityBBoxes(void);
8263 static void R_DrawModelDecals(void);
8264 extern void R_DrawModelShadows(void);
8265 extern void R_DrawModelShadowMaps(void);
8266 extern cvar_t cl_decals_newsystem;
8267 extern qboolean r_shadow_usingdeferredprepass;
8268 void R_RenderScene(void)
8269 {
8270         qboolean shadowmapping = false;
8271
8272         r_refdef.stats.renders++;
8273
8274         R_UpdateFogColor();
8275
8276         // don't let sound skip if going slow
8277         if (r_refdef.scene.extraupdate)
8278                 S_ExtraUpdate ();
8279
8280         R_MeshQueue_BeginScene();
8281
8282         R_SkyStartFrame();
8283
8284         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);
8285
8286         if (cl.csqc_vidvars.drawworld)
8287         {
8288                 // don't let sound skip if going slow
8289                 if (r_refdef.scene.extraupdate)
8290                         S_ExtraUpdate ();
8291
8292                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8293                 {
8294                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8295                         if (r_timereport_active)
8296                                 R_TimeReport("worldsky");
8297                 }
8298
8299                 if (R_DrawBrushModelsSky() && r_timereport_active)
8300                         R_TimeReport("bmodelsky");
8301
8302                 if (skyrendermasked && skyrenderlater)
8303                 {
8304                         // we have to force off the water clipping plane while rendering sky
8305                         R_SetupView(false);
8306                         R_Sky();
8307                         R_SetupView(true);
8308                         if (r_timereport_active)
8309                                 R_TimeReport("sky");
8310                 }
8311         }
8312
8313         R_AnimCache_CacheVisibleEntities();
8314         if (r_timereport_active)
8315                 R_TimeReport("animation");
8316
8317         R_Shadow_PrepareLights();
8318         if (r_timereport_active)
8319                 R_TimeReport("preparelights");
8320
8321         if (R_Shadow_ShadowMappingEnabled())
8322                 shadowmapping = true;
8323
8324         if (r_shadow_usingdeferredprepass)
8325                 R_Shadow_DrawPrepass();
8326
8327         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8328         {
8329                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8330                 if (r_timereport_active)
8331                         R_TimeReport("worlddepth");
8332         }
8333         if (r_depthfirst.integer >= 2)
8334         {
8335                 R_DrawModelsDepth();
8336                 if (r_timereport_active)
8337                         R_TimeReport("modeldepth");
8338         }
8339
8340         if (r_shadows.integer > 0 && shadowmapping && r_refdef.lightmapintensity > 0)
8341         {
8342                 R_DrawModelShadowMaps();
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 (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8350         {
8351                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8352                 if (r_timereport_active)
8353                         R_TimeReport("world");
8354         }
8355
8356         // don't let sound skip if going slow
8357         if (r_refdef.scene.extraupdate)
8358                 S_ExtraUpdate ();
8359
8360         R_DrawModels();
8361         if (r_timereport_active)
8362                 R_TimeReport("models");
8363
8364         // don't let sound skip if going slow
8365         if (r_refdef.scene.extraupdate)
8366                 S_ExtraUpdate ();
8367
8368         if (r_shadows.integer > 0 && !shadowmapping && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8369         {
8370                 R_DrawModelShadows();
8371                 R_ResetViewRendering3D();
8372                 // don't let sound skip if going slow
8373                 if (r_refdef.scene.extraupdate)
8374                         S_ExtraUpdate ();
8375         }
8376
8377         if (!r_shadow_usingdeferredprepass)
8378         {
8379                 R_Shadow_DrawLights();
8380                 if (r_timereport_active)
8381                         R_TimeReport("rtlights");
8382         }
8383
8384         // don't let sound skip if going slow
8385         if (r_refdef.scene.extraupdate)
8386                 S_ExtraUpdate ();
8387
8388         if (r_shadows.integer > 0 && !shadowmapping && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8389         {
8390                 R_DrawModelShadows();
8391                 R_ResetViewRendering3D();
8392                 // don't let sound skip if going slow
8393                 if (r_refdef.scene.extraupdate)
8394                         S_ExtraUpdate ();
8395         }
8396
8397         if (cl.csqc_vidvars.drawworld)
8398         {
8399                 if (cl_decals_newsystem.integer)
8400                 {
8401                         R_DrawModelDecals();
8402                         if (r_timereport_active)
8403                                 R_TimeReport("modeldecals");
8404                 }
8405                 else
8406                 {
8407                         R_DrawDecals();
8408                         if (r_timereport_active)
8409                                 R_TimeReport("decals");
8410                 }
8411
8412                 R_DrawParticles();
8413                 if (r_timereport_active)
8414                         R_TimeReport("particles");
8415
8416                 R_DrawExplosions();
8417                 if (r_timereport_active)
8418                         R_TimeReport("explosions");
8419
8420                 R_DrawLightningBeams();
8421                 if (r_timereport_active)
8422                         R_TimeReport("lightning");
8423         }
8424
8425         VM_CL_AddPolygonsToMeshQueue();
8426
8427         if (r_refdef.view.showdebug)
8428         {
8429                 if (cl_locs_show.integer)
8430                 {
8431                         R_DrawLocs();
8432                         if (r_timereport_active)
8433                                 R_TimeReport("showlocs");
8434                 }
8435
8436                 if (r_drawportals.integer)
8437                 {
8438                         R_DrawPortals();
8439                         if (r_timereport_active)
8440                                 R_TimeReport("portals");
8441                 }
8442
8443                 if (r_showbboxes.value > 0)
8444                 {
8445                         R_DrawEntityBBoxes();
8446                         if (r_timereport_active)
8447                                 R_TimeReport("bboxes");
8448                 }
8449         }
8450
8451         R_MeshQueue_RenderTransparent();
8452         if (r_timereport_active)
8453                 R_TimeReport("drawtrans");
8454
8455         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))
8456         {
8457                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8458                 if (r_timereport_active)
8459                         R_TimeReport("worlddebug");
8460                 R_DrawModelsDebug();
8461                 if (r_timereport_active)
8462                         R_TimeReport("modeldebug");
8463         }
8464
8465         if (cl.csqc_vidvars.drawworld)
8466         {
8467                 R_Shadow_DrawCoronas();
8468                 if (r_timereport_active)
8469                         R_TimeReport("coronas");
8470         }
8471
8472         // don't let sound skip if going slow
8473         if (r_refdef.scene.extraupdate)
8474                 S_ExtraUpdate ();
8475
8476         R_ResetViewRendering2D();
8477 }
8478
8479 static const unsigned short bboxelements[36] =
8480 {
8481         5, 1, 3, 5, 3, 7,
8482         6, 2, 0, 6, 0, 4,
8483         7, 3, 2, 7, 2, 6,
8484         4, 0, 1, 4, 1, 5,
8485         4, 5, 7, 4, 7, 6,
8486         1, 0, 2, 1, 2, 3,
8487 };
8488
8489 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8490 {
8491         int i;
8492         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8493
8494         RSurf_ActiveWorldEntity();
8495
8496         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8497         GL_DepthMask(false);
8498         GL_DepthRange(0, 1);
8499         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8500         R_Mesh_ResetTextureState();
8501
8502         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8503         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8504         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8505         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8506         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8507         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8508         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8509         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8510         R_FillColors(color4f, 8, cr, cg, cb, ca);
8511         if (r_refdef.fogenabled)
8512         {
8513                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8514                 {
8515                         f1 = RSurf_FogVertex(v);
8516                         f2 = 1 - f1;
8517                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8518                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8519                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8520                 }
8521         }
8522         R_Mesh_VertexPointer(vertex3f, 0, 0);
8523         R_Mesh_ColorPointer(color4f, 0, 0);
8524         R_Mesh_ResetTextureState();
8525         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8526         R_Mesh_Draw(0, 8, 0, 12, NULL, bboxelements, 0, 0);
8527 }
8528
8529 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8530 {
8531         int i;
8532         float color[4];
8533         prvm_edict_t *edict;
8534         prvm_prog_t *prog_save = prog;
8535
8536         // this function draws bounding boxes of server entities
8537         if (!sv.active)
8538                 return;
8539
8540         GL_CullFace(GL_NONE);
8541         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8542
8543         prog = 0;
8544         SV_VM_Begin();
8545         for (i = 0;i < numsurfaces;i++)
8546         {
8547                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8548                 switch ((int)edict->fields.server->solid)
8549                 {
8550                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8551                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8552                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8553                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8554                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8555                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8556                 }
8557                 color[3] *= r_showbboxes.value;
8558                 color[3] = bound(0, color[3], 1);
8559                 GL_DepthTest(!r_showdisabledepthtest.integer);
8560                 GL_CullFace(r_refdef.view.cullface_front);
8561                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8562         }
8563         SV_VM_End();
8564         prog = prog_save;
8565 }
8566
8567 static void R_DrawEntityBBoxes(void)
8568 {
8569         int i;
8570         prvm_edict_t *edict;
8571         vec3_t center;
8572         prvm_prog_t *prog_save = prog;
8573
8574         // this function draws bounding boxes of server entities
8575         if (!sv.active)
8576                 return;
8577
8578         prog = 0;
8579         SV_VM_Begin();
8580         for (i = 0;i < prog->num_edicts;i++)
8581         {
8582                 edict = PRVM_EDICT_NUM(i);
8583                 if (edict->priv.server->free)
8584                         continue;
8585                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8586                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8587                         continue;
8588                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8589                         continue;
8590                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8591                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8592         }
8593         SV_VM_End();
8594         prog = prog_save;
8595 }
8596
8597 static const int nomodelelement3i[24] =
8598 {
8599         5, 2, 0,
8600         5, 1, 2,
8601         5, 0, 3,
8602         5, 3, 1,
8603         0, 2, 4,
8604         2, 1, 4,
8605         3, 0, 4,
8606         1, 3, 4
8607 };
8608
8609 static const unsigned short nomodelelement3s[24] =
8610 {
8611         5, 2, 0,
8612         5, 1, 2,
8613         5, 0, 3,
8614         5, 3, 1,
8615         0, 2, 4,
8616         2, 1, 4,
8617         3, 0, 4,
8618         1, 3, 4
8619 };
8620
8621 static const float nomodelvertex3f[6*3] =
8622 {
8623         -16,   0,   0,
8624          16,   0,   0,
8625           0, -16,   0,
8626           0,  16,   0,
8627           0,   0, -16,
8628           0,   0,  16
8629 };
8630
8631 static const float nomodelcolor4f[6*4] =
8632 {
8633         0.0f, 0.0f, 0.5f, 1.0f,
8634         0.0f, 0.0f, 0.5f, 1.0f,
8635         0.0f, 0.5f, 0.0f, 1.0f,
8636         0.0f, 0.5f, 0.0f, 1.0f,
8637         0.5f, 0.0f, 0.0f, 1.0f,
8638         0.5f, 0.0f, 0.0f, 1.0f
8639 };
8640
8641 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8642 {
8643         int i;
8644         float f1, f2, *c;
8645         float color4f[6*4];
8646
8647         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);
8648
8649         // this is only called once per entity so numsurfaces is always 1, and
8650         // surfacelist is always {0}, so this code does not handle batches
8651
8652         if (rsurface.ent_flags & RENDER_ADDITIVE)
8653         {
8654                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8655                 GL_DepthMask(false);
8656         }
8657         else if (rsurface.colormod[3] < 1)
8658         {
8659                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8660                 GL_DepthMask(false);
8661         }
8662         else
8663         {
8664                 GL_BlendFunc(GL_ONE, GL_ZERO);
8665                 GL_DepthMask(true);
8666         }
8667         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8668         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8669         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8670         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8671         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8672         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
8673         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8674         R_Mesh_ColorPointer(color4f, 0, 0);
8675         for (i = 0, c = color4f;i < 6;i++, c += 4)
8676         {
8677                 c[0] *= rsurface.colormod[0];
8678                 c[1] *= rsurface.colormod[1];
8679                 c[2] *= rsurface.colormod[2];
8680                 c[3] *= rsurface.colormod[3];
8681         }
8682         if (r_refdef.fogenabled)
8683         {
8684                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8685                 {
8686                         f1 = RSurf_FogVertex(rsurface.vertex3f + 3*i);
8687                         f2 = 1 - f1;
8688                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8689                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8690                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8691                 }
8692         }
8693         R_Mesh_ResetTextureState();
8694         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, nomodelelement3s, 0, 0);
8695 }
8696
8697 void R_DrawNoModel(entity_render_t *ent)
8698 {
8699         vec3_t org;
8700         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8701         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8702                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8703         else
8704                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8705 }
8706
8707 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8708 {
8709         vec3_t right1, right2, diff, normal;
8710
8711         VectorSubtract (org2, org1, normal);
8712
8713         // calculate 'right' vector for start
8714         VectorSubtract (r_refdef.view.origin, org1, diff);
8715         CrossProduct (normal, diff, right1);
8716         VectorNormalize (right1);
8717
8718         // calculate 'right' vector for end
8719         VectorSubtract (r_refdef.view.origin, org2, diff);
8720         CrossProduct (normal, diff, right2);
8721         VectorNormalize (right2);
8722
8723         vert[ 0] = org1[0] + width * right1[0];
8724         vert[ 1] = org1[1] + width * right1[1];
8725         vert[ 2] = org1[2] + width * right1[2];
8726         vert[ 3] = org1[0] - width * right1[0];
8727         vert[ 4] = org1[1] - width * right1[1];
8728         vert[ 5] = org1[2] - width * right1[2];
8729         vert[ 6] = org2[0] - width * right2[0];
8730         vert[ 7] = org2[1] - width * right2[1];
8731         vert[ 8] = org2[2] - width * right2[2];
8732         vert[ 9] = org2[0] + width * right2[0];
8733         vert[10] = org2[1] + width * right2[1];
8734         vert[11] = org2[2] + width * right2[2];
8735 }
8736
8737 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)
8738 {
8739         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8740         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8741         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8742         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8743         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8744         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8745         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8746         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8747         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8748         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8749         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8750         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8751 }
8752
8753 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8754 {
8755         int i;
8756         float *vertex3f;
8757         float v[3];
8758         VectorSet(v, x, y, z);
8759         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8760                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8761                         break;
8762         if (i == mesh->numvertices)
8763         {
8764                 if (mesh->numvertices < mesh->maxvertices)
8765                 {
8766                         VectorCopy(v, vertex3f);
8767                         mesh->numvertices++;
8768                 }
8769                 return mesh->numvertices;
8770         }
8771         else
8772                 return i;
8773 }
8774
8775 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8776 {
8777         int i;
8778         int *e, element[3];
8779         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8780         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8781         e = mesh->element3i + mesh->numtriangles * 3;
8782         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8783         {
8784                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8785                 if (mesh->numtriangles < mesh->maxtriangles)
8786                 {
8787                         *e++ = element[0];
8788                         *e++ = element[1];
8789                         *e++ = element[2];
8790                         mesh->numtriangles++;
8791                 }
8792                 element[1] = element[2];
8793         }
8794 }
8795
8796 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8797 {
8798         int i;
8799         int *e, element[3];
8800         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8801         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8802         e = mesh->element3i + mesh->numtriangles * 3;
8803         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8804         {
8805                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8806                 if (mesh->numtriangles < mesh->maxtriangles)
8807                 {
8808                         *e++ = element[0];
8809                         *e++ = element[1];
8810                         *e++ = element[2];
8811                         mesh->numtriangles++;
8812                 }
8813                 element[1] = element[2];
8814         }
8815 }
8816
8817 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8818 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8819 {
8820         int planenum, planenum2;
8821         int w;
8822         int tempnumpoints;
8823         mplane_t *plane, *plane2;
8824         double maxdist;
8825         double temppoints[2][256*3];
8826         // figure out how large a bounding box we need to properly compute this brush
8827         maxdist = 0;
8828         for (w = 0;w < numplanes;w++)
8829                 maxdist = max(maxdist, fabs(planes[w].dist));
8830         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8831         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8832         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8833         {
8834                 w = 0;
8835                 tempnumpoints = 4;
8836                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8837                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8838                 {
8839                         if (planenum2 == planenum)
8840                                 continue;
8841                         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);
8842                         w = !w;
8843                 }
8844                 if (tempnumpoints < 3)
8845                         continue;
8846                 // generate elements forming a triangle fan for this polygon
8847                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8848         }
8849 }
8850
8851 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)
8852 {
8853         texturelayer_t *layer;
8854         layer = t->currentlayers + t->currentnumlayers++;
8855         layer->type = type;
8856         layer->depthmask = depthmask;
8857         layer->blendfunc1 = blendfunc1;
8858         layer->blendfunc2 = blendfunc2;
8859         layer->texture = texture;
8860         layer->texmatrix = *matrix;
8861         layer->color[0] = r;
8862         layer->color[1] = g;
8863         layer->color[2] = b;
8864         layer->color[3] = a;
8865 }
8866
8867 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8868 {
8869         double index, f;
8870         index = parms[2] + r_refdef.scene.time * parms[3];
8871         index -= floor(index);
8872         switch (func)
8873         {
8874         default:
8875         case Q3WAVEFUNC_NONE:
8876         case Q3WAVEFUNC_NOISE:
8877         case Q3WAVEFUNC_COUNT:
8878                 f = 0;
8879                 break;
8880         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8881         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8882         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8883         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8884         case Q3WAVEFUNC_TRIANGLE:
8885                 index *= 4;
8886                 f = index - floor(index);
8887                 if (index < 1)
8888                         f = f;
8889                 else if (index < 2)
8890                         f = 1 - f;
8891                 else if (index < 3)
8892                         f = -f;
8893                 else
8894                         f = -(1 - f);
8895                 break;
8896         }
8897         return (float)(parms[0] + parms[1] * f);
8898 }
8899
8900 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8901 {
8902         int w, h, idx;
8903         float f;
8904         float tcmat[12];
8905         matrix4x4_t matrix, temp;
8906         switch(tcmod->tcmod)
8907         {
8908                 case Q3TCMOD_COUNT:
8909                 case Q3TCMOD_NONE:
8910                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8911                                 matrix = r_waterscrollmatrix;
8912                         else
8913                                 matrix = identitymatrix;
8914                         break;
8915                 case Q3TCMOD_ENTITYTRANSLATE:
8916                         // this is used in Q3 to allow the gamecode to control texcoord
8917                         // scrolling on the entity, which is not supported in darkplaces yet.
8918                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8919                         break;
8920                 case Q3TCMOD_ROTATE:
8921                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8922                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
8923                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8924                         break;
8925                 case Q3TCMOD_SCALE:
8926                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8927                         break;
8928                 case Q3TCMOD_SCROLL:
8929                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
8930                         break;
8931                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8932                         w = (int) tcmod->parms[0];
8933                         h = (int) tcmod->parms[1];
8934                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
8935                         f = f - floor(f);
8936                         idx = (int) floor(f * w * h);
8937                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8938                         break;
8939                 case Q3TCMOD_STRETCH:
8940                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8941                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8942                         break;
8943                 case Q3TCMOD_TRANSFORM:
8944                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8945                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8946                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8947                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8948                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8949                         break;
8950                 case Q3TCMOD_TURBULENT:
8951                         // this is handled in the RSurf_PrepareVertices function
8952                         matrix = identitymatrix;
8953                         break;
8954         }
8955         temp = *texmatrix;
8956         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8957 }
8958
8959 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8960 {
8961         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
8962         char name[MAX_QPATH];
8963         skinframe_t *skinframe;
8964         unsigned char pixels[296*194];
8965         strlcpy(cache->name, skinname, sizeof(cache->name));
8966         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8967         if (developer_loading.integer)
8968                 Con_Printf("loading %s\n", name);
8969         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8970         if (!skinframe || !skinframe->base)
8971         {
8972                 unsigned char *f;
8973                 fs_offset_t filesize;
8974                 skinframe = NULL;
8975                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8976                 if (f)
8977                 {
8978                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8979                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8980                         Mem_Free(f);
8981                 }
8982         }
8983         cache->skinframe = skinframe;
8984 }
8985
8986 texture_t *R_GetCurrentTexture(texture_t *t)
8987 {
8988         int i;
8989         const entity_render_t *ent = rsurface.entity;
8990         dp_model_t *model = ent->model;
8991         q3shaderinfo_layer_tcmod_t *tcmod;
8992
8993         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
8994                 return t->currentframe;
8995         t->update_lastrenderframe = r_textureframe;
8996         t->update_lastrenderentity = (void *)ent;
8997
8998         // switch to an alternate material if this is a q1bsp animated material
8999         {
9000                 texture_t *texture = t;
9001                 int s = rsurface.ent_skinnum;
9002                 if ((unsigned int)s >= (unsigned int)model->numskins)
9003                         s = 0;
9004                 if (model->skinscenes)
9005                 {
9006                         if (model->skinscenes[s].framecount > 1)
9007                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9008                         else
9009                                 s = model->skinscenes[s].firstframe;
9010                 }
9011                 if (s > 0)
9012                         t = t + s * model->num_surfaces;
9013                 if (t->animated)
9014                 {
9015                         // use an alternate animation if the entity's frame is not 0,
9016                         // and only if the texture has an alternate animation
9017                         if (rsurface.ent_alttextures && t->anim_total[1])
9018                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9019                         else
9020                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9021                 }
9022                 texture->currentframe = t;
9023         }
9024
9025         // update currentskinframe to be a qw skin or animation frame
9026         if (rsurface.ent_qwskin >= 0)
9027         {
9028                 i = rsurface.ent_qwskin;
9029                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9030                 {
9031                         r_qwskincache_size = cl.maxclients;
9032                         if (r_qwskincache)
9033                                 Mem_Free(r_qwskincache);
9034                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9035                 }
9036                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9037                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9038                 t->currentskinframe = r_qwskincache[i].skinframe;
9039                 if (t->currentskinframe == NULL)
9040                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9041         }
9042         else if (t->numskinframes >= 2)
9043                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9044         if (t->backgroundnumskinframes >= 2)
9045                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9046
9047         t->currentmaterialflags = t->basematerialflags;
9048         t->currentalpha = rsurface.colormod[3];
9049         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9050                 t->currentalpha *= r_wateralpha.value;
9051         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9052                 t->currentalpha *= t->r_water_wateralpha;
9053         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9054                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION);
9055         if (!(rsurface.ent_flags & RENDER_LIGHT))
9056                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9057         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9058         {
9059                 // pick a model lighting mode
9060                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9061                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9062                 else
9063                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9064         }
9065         if (rsurface.ent_flags & RENDER_ADDITIVE)
9066                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9067         else if (t->currentalpha < 1)
9068                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9069         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9070                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9071         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9072                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9073         if (t->backgroundnumskinframes)
9074                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9075         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9076         {
9077                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER))
9078                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9079         }
9080         else
9081                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER);
9082         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9083                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9084
9085         // there is no tcmod
9086         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9087         {
9088                 t->currenttexmatrix = r_waterscrollmatrix;
9089                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9090         }
9091         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9092         {
9093                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9094                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9095         }
9096
9097         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9098                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9099         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9100                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9101
9102         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9103         if (t->currentskinframe->qpixels)
9104                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9105         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9106         if (!t->basetexture)
9107                 t->basetexture = r_texture_notexture;
9108         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9109         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9110         t->nmaptexture = t->currentskinframe->nmap;
9111         if (!t->nmaptexture)
9112                 t->nmaptexture = r_texture_blanknormalmap;
9113         t->glosstexture = r_texture_black;
9114         t->glowtexture = t->currentskinframe->glow;
9115         t->fogtexture = t->currentskinframe->fog;
9116         t->reflectmasktexture = t->currentskinframe->reflect;
9117         if (t->backgroundnumskinframes)
9118         {
9119                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9120                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9121                 t->backgroundglosstexture = r_texture_black;
9122                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9123                 if (!t->backgroundnmaptexture)
9124                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9125         }
9126         else
9127         {
9128                 t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
9129                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9130                 t->backgroundglosstexture = r_texture_black;
9131                 t->backgroundglowtexture = NULL;
9132         }
9133         t->specularpower = r_shadow_glossexponent.value;
9134         // TODO: store reference values for these in the texture?
9135         t->specularscale = 0;
9136         if (r_shadow_gloss.integer > 0)
9137         {
9138                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9139                 {
9140                         if (r_shadow_glossintensity.value > 0)
9141                         {
9142                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9143                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9144                                 t->specularscale = r_shadow_glossintensity.value;
9145                         }
9146                 }
9147                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9148                 {
9149                         t->glosstexture = r_texture_white;
9150                         t->backgroundglosstexture = r_texture_white;
9151                         t->specularscale = r_shadow_gloss2intensity.value;
9152                         t->specularpower = r_shadow_gloss2exponent.value;
9153                 }
9154         }
9155         t->specularscale *= t->specularscalemod;
9156         t->specularpower *= t->specularpowermod;
9157
9158         // lightmaps mode looks bad with dlights using actual texturing, so turn
9159         // off the colormap and glossmap, but leave the normalmap on as it still
9160         // accurately represents the shading involved
9161         if (gl_lightmaps.integer)
9162         {
9163                 t->basetexture = r_texture_grey128;
9164                 t->pantstexture = r_texture_black;
9165                 t->shirttexture = r_texture_black;
9166                 t->nmaptexture = r_texture_blanknormalmap;
9167                 t->glosstexture = r_texture_black;
9168                 t->glowtexture = NULL;
9169                 t->fogtexture = NULL;
9170                 t->reflectmasktexture = NULL;
9171                 t->backgroundbasetexture = NULL;
9172                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9173                 t->backgroundglosstexture = r_texture_black;
9174                 t->backgroundglowtexture = NULL;
9175                 t->specularscale = 0;
9176                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9177         }
9178
9179         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9180         VectorClear(t->dlightcolor);
9181         t->currentnumlayers = 0;
9182         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9183         {
9184                 int blendfunc1, blendfunc2;
9185                 qboolean depthmask;
9186                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9187                 {
9188                         blendfunc1 = GL_SRC_ALPHA;
9189                         blendfunc2 = GL_ONE;
9190                 }
9191                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9192                 {
9193                         blendfunc1 = GL_SRC_ALPHA;
9194                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9195                 }
9196                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9197                 {
9198                         blendfunc1 = t->customblendfunc[0];
9199                         blendfunc2 = t->customblendfunc[1];
9200                 }
9201                 else
9202                 {
9203                         blendfunc1 = GL_ONE;
9204                         blendfunc2 = GL_ZERO;
9205                 }
9206                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9207                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9208                 {
9209                         // fullbright is not affected by r_refdef.lightmapintensity
9210                         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]);
9211                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9212                                 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]);
9213                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9214                                 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]);
9215                 }
9216                 else
9217                 {
9218                         vec3_t ambientcolor;
9219                         float colorscale;
9220                         // set the color tint used for lights affecting this surface
9221                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9222                         colorscale = 2;
9223                         // q3bsp has no lightmap updates, so the lightstylevalue that
9224                         // would normally be baked into the lightmap must be
9225                         // applied to the color
9226                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9227                         if (model->type == mod_brushq3)
9228                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9229                         colorscale *= r_refdef.lightmapintensity;
9230                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9231                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9232                         // basic lit geometry
9233                         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]);
9234                         // add pants/shirt if needed
9235                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9236                                 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]);
9237                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9238                                 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]);
9239                         // now add ambient passes if needed
9240                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9241                         {
9242                                 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]);
9243                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9244                                         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]);
9245                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9246                                         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]);
9247                         }
9248                 }
9249                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9250                         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]);
9251                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9252                 {
9253                         // if this is opaque use alpha blend which will darken the earlier
9254                         // passes cheaply.
9255                         //
9256                         // if this is an alpha blended material, all the earlier passes
9257                         // were darkened by fog already, so we only need to add the fog
9258                         // color ontop through the fog mask texture
9259                         //
9260                         // if this is an additive blended material, all the earlier passes
9261                         // were darkened by fog already, and we should not add fog color
9262                         // (because the background was not darkened, there is no fog color
9263                         // that was lost behind it).
9264                         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]);
9265                 }
9266         }
9267
9268         return t->currentframe;
9269 }
9270
9271 rsurfacestate_t rsurface;
9272
9273 void R_Mesh_ResizeArrays(int newvertices)
9274 {
9275         float *base;
9276         if (rsurface.array_size >= newvertices)
9277                 return;
9278         if (rsurface.array_modelvertex3f)
9279                 Mem_Free(rsurface.array_modelvertex3f);
9280         rsurface.array_size = (newvertices + 1023) & ~1023;
9281         base = (float *)Mem_Alloc(r_main_mempool, rsurface.array_size * sizeof(float[33]));
9282         rsurface.array_modelvertex3f     = base + rsurface.array_size * 0;
9283         rsurface.array_modelsvector3f    = base + rsurface.array_size * 3;
9284         rsurface.array_modeltvector3f    = base + rsurface.array_size * 6;
9285         rsurface.array_modelnormal3f     = base + rsurface.array_size * 9;
9286         rsurface.array_deformedvertex3f  = base + rsurface.array_size * 12;
9287         rsurface.array_deformedsvector3f = base + rsurface.array_size * 15;
9288         rsurface.array_deformedtvector3f = base + rsurface.array_size * 18;
9289         rsurface.array_deformednormal3f  = base + rsurface.array_size * 21;
9290         rsurface.array_texcoord3f        = base + rsurface.array_size * 24;
9291         rsurface.array_color4f           = base + rsurface.array_size * 27;
9292         rsurface.array_generatedtexcoordtexture2f = base + rsurface.array_size * 31;
9293 }
9294
9295 void RSurf_ActiveWorldEntity(void)
9296 {
9297         dp_model_t *model = r_refdef.scene.worldmodel;
9298         //if (rsurface.entity == r_refdef.scene.worldentity)
9299         //      return;
9300         rsurface.entity = r_refdef.scene.worldentity;
9301         rsurface.skeleton = NULL;
9302         rsurface.ent_skinnum = 0;
9303         rsurface.ent_qwskin = -1;
9304         rsurface.ent_shadertime = 0;
9305         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9306         if (rsurface.array_size < model->surfmesh.num_vertices)
9307                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9308         rsurface.matrix = identitymatrix;
9309         rsurface.inversematrix = identitymatrix;
9310         rsurface.matrixscale = 1;
9311         rsurface.inversematrixscale = 1;
9312         R_EntityMatrix(&identitymatrix);
9313         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9314         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9315         rsurface.fograngerecip = r_refdef.fograngerecip;
9316         rsurface.fogheightfade = r_refdef.fogheightfade;
9317         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9318         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9319         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9320         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9321         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9322         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9323         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9324         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9325         rsurface.colormod[3] = 1;
9326         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);
9327         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9328         rsurface.frameblend[0].lerp = 1;
9329         rsurface.ent_alttextures = false;
9330         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9331         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9332         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9333         rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9334         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9335         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9336         rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9337         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9338         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9339         rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9340         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9341         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9342         rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9343         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9344         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9345         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9346         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9347         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9348         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9349         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9350         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9351         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9352         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9353         rsurface.modelelement3i = model->surfmesh.data_element3i;
9354         rsurface.modelelement3s = model->surfmesh.data_element3s;
9355         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9356         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9357         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9358         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9359         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9360         rsurface.modelsurfaces = model->data_surfaces;
9361         rsurface.generatedvertex = false;
9362         rsurface.vertex3f  = rsurface.modelvertex3f;
9363         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9364         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9365         rsurface.svector3f = rsurface.modelsvector3f;
9366         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9367         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9368         rsurface.tvector3f = rsurface.modeltvector3f;
9369         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9370         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9371         rsurface.normal3f  = rsurface.modelnormal3f;
9372         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9373         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9374         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9375 }
9376
9377 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9378 {
9379         dp_model_t *model = ent->model;
9380         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9381         //      return;
9382         rsurface.entity = (entity_render_t *)ent;
9383         rsurface.skeleton = ent->skeleton;
9384         rsurface.ent_skinnum = ent->skinnum;
9385         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;
9386         rsurface.ent_shadertime = ent->shadertime;
9387         rsurface.ent_flags = ent->flags;
9388         if (rsurface.array_size < model->surfmesh.num_vertices)
9389                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9390         rsurface.matrix = ent->matrix;
9391         rsurface.inversematrix = ent->inversematrix;
9392         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9393         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9394         R_EntityMatrix(&rsurface.matrix);
9395         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9396         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9397         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9398         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9399         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9400         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9401         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9402         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9403         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9404         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9405         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9406         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9407         rsurface.colormod[3] = ent->alpha;
9408         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9409         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9410         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9411         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9412         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9413         if (ent->model->brush.submodel && !prepass)
9414         {
9415                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9416                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9417         }
9418         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9419         {
9420                 if (ent->animcache_vertex3f && !r_framedata_failed)
9421                 {
9422                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9423                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9424                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9425                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9426                 }
9427                 else if (wanttangents)
9428                 {
9429                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9430                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9431                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9432                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9433                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9434                 }
9435                 else if (wantnormals)
9436                 {
9437                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9438                         rsurface.modelsvector3f = NULL;
9439                         rsurface.modeltvector3f = NULL;
9440                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9441                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9442                 }
9443                 else
9444                 {
9445                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9446                         rsurface.modelsvector3f = NULL;
9447                         rsurface.modeltvector3f = NULL;
9448                         rsurface.modelnormal3f = NULL;
9449                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9450                 }
9451                 rsurface.modelvertex3f_bufferobject = 0;
9452                 rsurface.modelvertex3f_bufferoffset = 0;
9453                 rsurface.modelsvector3f_bufferobject = 0;
9454                 rsurface.modelsvector3f_bufferoffset = 0;
9455                 rsurface.modeltvector3f_bufferobject = 0;
9456                 rsurface.modeltvector3f_bufferoffset = 0;
9457                 rsurface.modelnormal3f_bufferobject = 0;
9458                 rsurface.modelnormal3f_bufferoffset = 0;
9459                 rsurface.generatedvertex = true;
9460         }
9461         else
9462         {
9463                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9464                 rsurface.modelvertex3f_bufferobject = model->surfmesh.vbo;
9465                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9466                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9467                 rsurface.modelsvector3f_bufferobject = model->surfmesh.vbo;
9468                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9469                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9470                 rsurface.modeltvector3f_bufferobject = model->surfmesh.vbo;
9471                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9472                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9473                 rsurface.modelnormal3f_bufferobject = model->surfmesh.vbo;
9474                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9475                 rsurface.generatedvertex = false;
9476         }
9477         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9478         rsurface.modellightmapcolor4f_bufferobject = model->surfmesh.vbo;
9479         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9480         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9481         rsurface.modeltexcoordtexture2f_bufferobject = model->surfmesh.vbo;
9482         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9483         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9484         rsurface.modeltexcoordlightmap2f_bufferobject = model->surfmesh.vbo;
9485         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9486         rsurface.modelelement3i = model->surfmesh.data_element3i;
9487         rsurface.modelelement3s = model->surfmesh.data_element3s;
9488         rsurface.modelelement3i_bufferobject = model->surfmesh.ebo3i;
9489         rsurface.modelelement3s_bufferobject = model->surfmesh.ebo3s;
9490         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9491         rsurface.modelnum_vertices = model->surfmesh.num_vertices;
9492         rsurface.modelnum_triangles = model->surfmesh.num_triangles;
9493         rsurface.modelsurfaces = model->data_surfaces;
9494         rsurface.vertex3f  = rsurface.modelvertex3f;
9495         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9496         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9497         rsurface.svector3f = rsurface.modelsvector3f;
9498         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9499         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9500         rsurface.tvector3f = rsurface.modeltvector3f;
9501         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9502         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9503         rsurface.normal3f  = rsurface.modelnormal3f;
9504         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9505         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9506         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9507 }
9508
9509 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)
9510 {
9511         rsurface.entity = r_refdef.scene.worldentity;
9512         rsurface.skeleton = NULL;
9513         rsurface.ent_skinnum = 0;
9514         rsurface.ent_qwskin = -1;
9515         rsurface.ent_shadertime = shadertime;
9516         rsurface.ent_flags = entflags;
9517         rsurface.modelnum_vertices = numvertices;
9518         rsurface.modelnum_triangles = numtriangles;
9519         if (rsurface.array_size < rsurface.modelnum_vertices)
9520                 R_Mesh_ResizeArrays(rsurface.modelnum_vertices);
9521         rsurface.matrix = *matrix;
9522         rsurface.inversematrix = *inversematrix;
9523         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9524         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9525         R_EntityMatrix(&rsurface.matrix);
9526         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9527         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9528         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9529         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9530         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9531         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9532         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9533         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9534         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9535         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9536         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9537         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9538         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);
9539         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9540         rsurface.frameblend[0].lerp = 1;
9541         rsurface.ent_alttextures = false;
9542         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9543         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9544         if (wanttangents)
9545         {
9546                 rsurface.modelvertex3f = vertex3f;
9547                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9548                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9549                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9550         }
9551         else if (wantnormals)
9552         {
9553                 rsurface.modelvertex3f = vertex3f;
9554                 rsurface.modelsvector3f = NULL;
9555                 rsurface.modeltvector3f = NULL;
9556                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9557         }
9558         else
9559         {
9560                 rsurface.modelvertex3f = vertex3f;
9561                 rsurface.modelsvector3f = NULL;
9562                 rsurface.modeltvector3f = NULL;
9563                 rsurface.modelnormal3f = NULL;
9564         }
9565         rsurface.modelvertex3f_bufferobject = 0;
9566         rsurface.modelvertex3f_bufferoffset = 0;
9567         rsurface.modelsvector3f_bufferobject = 0;
9568         rsurface.modelsvector3f_bufferoffset = 0;
9569         rsurface.modeltvector3f_bufferobject = 0;
9570         rsurface.modeltvector3f_bufferoffset = 0;
9571         rsurface.modelnormal3f_bufferobject = 0;
9572         rsurface.modelnormal3f_bufferoffset = 0;
9573         rsurface.generatedvertex = true;
9574         rsurface.modellightmapcolor4f  = color4f;
9575         rsurface.modellightmapcolor4f_bufferobject = 0;
9576         rsurface.modellightmapcolor4f_bufferoffset = 0;
9577         rsurface.modeltexcoordtexture2f  = texcoord2f;
9578         rsurface.modeltexcoordtexture2f_bufferobject = 0;
9579         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9580         rsurface.modeltexcoordlightmap2f  = NULL;
9581         rsurface.modeltexcoordlightmap2f_bufferobject = 0;
9582         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9583         rsurface.modelelement3i = element3i;
9584         rsurface.modelelement3s = element3s;
9585         rsurface.modelelement3i_bufferobject = 0;
9586         rsurface.modelelement3s_bufferobject = 0;
9587         rsurface.modellightmapoffsets = NULL;
9588         rsurface.modelsurfaces = NULL;
9589         rsurface.vertex3f  = rsurface.modelvertex3f;
9590         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9591         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9592         rsurface.svector3f = rsurface.modelsvector3f;
9593         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9594         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9595         rsurface.tvector3f = rsurface.modeltvector3f;
9596         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9597         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9598         rsurface.normal3f  = rsurface.modelnormal3f;
9599         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9600         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9601         rsurface.texcoordtexture2f = rsurface.modeltexcoordtexture2f;
9602
9603         if (rsurface.modelnum_vertices && rsurface.modelelement3i)
9604         {
9605                 if ((wantnormals || wanttangents) && !normal3f)
9606                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9607                 if (wanttangents && !svector3f)
9608                         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);
9609         }
9610 }
9611
9612 float RSurf_FogPoint(const float *v)
9613 {
9614         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9615         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9616         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9617         float FogHeightFade = r_refdef.fogheightfade;
9618         float fogfrac;
9619         unsigned int fogmasktableindex;
9620         if (r_refdef.fogplaneviewabove)
9621                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9622         else
9623                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9624         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9625         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9626 }
9627
9628 float RSurf_FogVertex(const float *v)
9629 {
9630         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9631         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9632         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9633         float FogHeightFade = rsurface.fogheightfade;
9634         float fogfrac;
9635         unsigned int fogmasktableindex;
9636         if (r_refdef.fogplaneviewabove)
9637                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9638         else
9639                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9640         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9641         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9642 }
9643
9644 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9645 void RSurf_PrepareVerticesForBatch(qboolean generatenormals, qboolean generatetangents, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9646 {
9647         int deformindex;
9648         int texturesurfaceindex;
9649         int i, j;
9650         float amplitude;
9651         float animpos;
9652         float scale;
9653         const float *v1, *in_tc;
9654         float *out_tc;
9655         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9656         float waveparms[4];
9657         q3shaderinfo_deform_t *deform;
9658         // 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
9659         if (rsurface.generatedvertex)
9660         {
9661                 if (rsurface.texture->tcgen.tcgen == Q3TCGEN_ENVIRONMENT)
9662                         generatenormals = true;
9663                 for (i = 0;i < Q3MAXDEFORMS;i++)
9664                 {
9665                         if (rsurface.texture->deforms[i].deform == Q3DEFORM_AUTOSPRITE)
9666                         {
9667                                 generatetangents = true;
9668                                 generatenormals = true;
9669                         }
9670                         if (rsurface.texture->deforms[i].deform != Q3DEFORM_NONE)
9671                                 generatenormals = true;
9672                 }
9673                 if (generatenormals && !rsurface.modelnormal3f)
9674                 {
9675                         rsurface.normal3f = rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9676                         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject = 0;
9677                         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset = 0;
9678                         Mod_BuildNormals(0, rsurface.modelnum_vertices, rsurface.modelnum_triangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9679                 }
9680                 if (generatetangents && !rsurface.modelsvector3f)
9681                 {
9682                         rsurface.svector3f = rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9683                         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject = 0;
9684                         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset = 0;
9685                         rsurface.tvector3f = rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9686                         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject = 0;
9687                         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset = 0;
9688                         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);
9689                 }
9690         }
9691         rsurface.vertex3f  = rsurface.modelvertex3f;
9692         rsurface.vertex3f_bufferobject = rsurface.modelvertex3f_bufferobject;
9693         rsurface.vertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9694         rsurface.svector3f = rsurface.modelsvector3f;
9695         rsurface.svector3f_bufferobject = rsurface.modelsvector3f_bufferobject;
9696         rsurface.svector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9697         rsurface.tvector3f = rsurface.modeltvector3f;
9698         rsurface.tvector3f_bufferobject = rsurface.modeltvector3f_bufferobject;
9699         rsurface.tvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9700         rsurface.normal3f  = rsurface.modelnormal3f;
9701         rsurface.normal3f_bufferobject = rsurface.modelnormal3f_bufferobject;
9702         rsurface.normal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9703         // if vertices are deformed (sprite flares and things in maps, possibly
9704         // water waves, bulges and other deformations), generate them into
9705         // rsurface.deform* arrays from whatever the rsurface.* arrays point to
9706         // (may be static model data or generated data for an animated model, or
9707         //  the previous deform pass)
9708         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
9709         {
9710                 switch (deform->deform)
9711                 {
9712                 default:
9713                 case Q3DEFORM_PROJECTIONSHADOW:
9714                 case Q3DEFORM_TEXT0:
9715                 case Q3DEFORM_TEXT1:
9716                 case Q3DEFORM_TEXT2:
9717                 case Q3DEFORM_TEXT3:
9718                 case Q3DEFORM_TEXT4:
9719                 case Q3DEFORM_TEXT5:
9720                 case Q3DEFORM_TEXT6:
9721                 case Q3DEFORM_TEXT7:
9722                 case Q3DEFORM_NONE:
9723                         break;
9724                 case Q3DEFORM_AUTOSPRITE:
9725                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9726                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9727                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9728                         VectorNormalize(newforward);
9729                         VectorNormalize(newright);
9730                         VectorNormalize(newup);
9731                         // make deformed versions of only the model vertices used by the specified surfaces
9732                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9733                         {
9734                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9735                                 // a single autosprite surface can contain multiple sprites...
9736                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9737                                 {
9738                                         VectorClear(center);
9739                                         for (i = 0;i < 4;i++)
9740                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9741                                         VectorScale(center, 0.25f, center);
9742                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, forward);
9743                                         VectorCopy((rsurface.svector3f + 3 * surface->num_firstvertex) + j*3, right);
9744                                         VectorCopy((rsurface.tvector3f + 3 * surface->num_firstvertex) + j*3, up);
9745                                         for (i = 0;i < 4;i++)
9746                                         {
9747                                                 VectorSubtract((rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i)*3, center, v);
9748                                                 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9749                                         }
9750                                 }
9751                                 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);
9752                                 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);
9753                         }
9754                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9755                         rsurface.vertex3f_bufferobject = 0;
9756                         rsurface.vertex3f_bufferoffset = 0;
9757                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9758                         rsurface.svector3f_bufferobject = 0;
9759                         rsurface.svector3f_bufferoffset = 0;
9760                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9761                         rsurface.tvector3f_bufferobject = 0;
9762                         rsurface.tvector3f_bufferoffset = 0;
9763                         rsurface.normal3f = rsurface.array_deformednormal3f;
9764                         rsurface.normal3f_bufferobject = 0;
9765                         rsurface.normal3f_bufferoffset = 0;
9766                         break;
9767                 case Q3DEFORM_AUTOSPRITE2:
9768                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9769                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9770                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9771                         VectorNormalize(newforward);
9772                         VectorNormalize(newright);
9773                         VectorNormalize(newup);
9774                         // make deformed versions of only the model vertices used by the specified surfaces
9775                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9776                         {
9777                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9778                                 const float *v1, *v2;
9779                                 vec3_t start, end;
9780                                 float f, l;
9781                                 struct
9782                                 {
9783                                         float length2;
9784                                         const float *v1;
9785                                         const float *v2;
9786                                 }
9787                                 shortest[2];
9788                                 memset(shortest, 0, sizeof(shortest));
9789                                 // a single autosprite surface can contain multiple sprites...
9790                                 for (j = 0;j < surface->num_vertices - 3;j += 4)
9791                                 {
9792                                         VectorClear(center);
9793                                         for (i = 0;i < 4;i++)
9794                                                 VectorAdd(center, (rsurface.vertex3f + 3 * surface->num_firstvertex) + (j+i) * 3, center);
9795                                         VectorScale(center, 0.25f, center);
9796                                         // find the two shortest edges, then use them to define the
9797                                         // axis vectors for rotating around the central axis
9798                                         for (i = 0;i < 6;i++)
9799                                         {
9800                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][0]);
9801                                                 v2 = rsurface.vertex3f + 3 * (surface->num_firstvertex + quadedges[i][1]);
9802 #if 0
9803                                                 Debug_PolygonBegin(NULL, 0);
9804                                                 Debug_PolygonVertex(v1[0], v1[1], v1[2], 0, 0, 1, 0, 0, 1);
9805                                                 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);
9806                                                 Debug_PolygonVertex(v2[0], v2[1], v2[2], 0, 0, 1, 0, 0, 1);
9807                                                 Debug_PolygonEnd();
9808 #endif
9809                                                 l = VectorDistance2(v1, v2);
9810                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9811                                                 if (v1[2] != v2[2])
9812                                                         l += (1.0f / 1024.0f);
9813                                                 if (shortest[0].length2 > l || i == 0)
9814                                                 {
9815                                                         shortest[1] = shortest[0];
9816                                                         shortest[0].length2 = l;
9817                                                         shortest[0].v1 = v1;
9818                                                         shortest[0].v2 = v2;
9819                                                 }
9820                                                 else if (shortest[1].length2 > l || i == 1)
9821                                                 {
9822                                                         shortest[1].length2 = l;
9823                                                         shortest[1].v1 = v1;
9824                                                         shortest[1].v2 = v2;
9825                                                 }
9826                                         }
9827                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9828                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9829 #if 0
9830                                         Debug_PolygonBegin(NULL, 0);
9831                                         Debug_PolygonVertex(start[0], start[1], start[2], 0, 0, 1, 1, 0, 1);
9832                                         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);
9833                                         Debug_PolygonVertex(end[0], end[1], end[2], 0, 0, 0, 1, 1, 1);
9834                                         Debug_PolygonEnd();
9835 #endif
9836                                         // this calculates the right vector from the shortest edge
9837                                         // and the up vector from the edge midpoints
9838                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9839                                         VectorNormalize(right);
9840                                         VectorSubtract(end, start, up);
9841                                         VectorNormalize(up);
9842                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9843                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9844                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9845                                         VectorNegate(forward, forward);
9846                                         VectorReflect(forward, 0, up, forward);
9847                                         VectorNormalize(forward);
9848                                         CrossProduct(up, forward, newright);
9849                                         VectorNormalize(newright);
9850 #if 0
9851                                         Debug_PolygonBegin(NULL, 0);
9852                                         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);
9853                                         Debug_PolygonVertex(center[0] + right[0] * 8, center[1] + right[1] * 8, center[2] + right[2] * 8, 0, 0, 0, 1, 0, 1);
9854                                         Debug_PolygonVertex(center[0] + up   [0] * 8, center[1] + up   [1] * 8, center[2] + up   [2] * 8, 0, 0, 0, 0, 1, 1);
9855                                         Debug_PolygonEnd();
9856 #endif
9857 #if 0
9858                                         Debug_PolygonBegin(NULL, 0);
9859                                         Debug_PolygonVertex(center[0] + forward [0] * 8, center[1] + forward [1] * 8, center[2] + forward [2] * 8, 0, 0, 1, 0, 0, 1);
9860                                         Debug_PolygonVertex(center[0] + newright[0] * 8, center[1] + newright[1] * 8, center[2] + newright[2] * 8, 0, 0, 0, 1, 0, 1);
9861                                         Debug_PolygonVertex(center[0] + up      [0] * 8, center[1] + up      [1] * 8, center[2] + up      [2] * 8, 0, 0, 0, 0, 1, 1);
9862                                         Debug_PolygonEnd();
9863 #endif
9864                                         // rotate the quad around the up axis vector, this is made
9865                                         // especially easy by the fact we know the quad is flat,
9866                                         // so we only have to subtract the center position and
9867                                         // measure distance along the right vector, and then
9868                                         // multiply that by the newright vector and add back the
9869                                         // center position
9870                                         // we also need to subtract the old position to undo the
9871                                         // displacement from the center, which we do with a
9872                                         // DotProduct, the subtraction/addition of center is also
9873                                         // optimized into DotProducts here
9874                                         l = DotProduct(right, center);
9875                                         for (i = 0;i < 4;i++)
9876                                         {
9877                                                 v1 = rsurface.vertex3f + 3 * (surface->num_firstvertex + j + i);
9878                                                 f = DotProduct(right, v1) - l;
9879                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_deformedvertex3f + (surface->num_firstvertex+i+j) * 3);
9880                                         }
9881                                 }
9882                                 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);
9883                                 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);
9884                         }
9885                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9886                         rsurface.vertex3f_bufferobject = 0;
9887                         rsurface.vertex3f_bufferoffset = 0;
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_NORMAL:
9899                         // deform the normals to make reflections wavey
9900                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9901                         {
9902                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9903                                 for (j = 0;j < surface->num_vertices;j++)
9904                                 {
9905                                         float vertex[3];
9906                                         float *normal = (rsurface.array_deformednormal3f  + 3 * surface->num_firstvertex) + j*3;
9907                                         VectorScale((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, 0.98f, vertex);
9908                                         VectorCopy((rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, normal);
9909                                         normal[0] += deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9910                                         normal[1] += deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9911                                         normal[2] += deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
9912                                         VectorNormalize(normal);
9913                                 }
9914                                 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);
9915                         }
9916                         rsurface.svector3f = rsurface.array_deformedsvector3f;
9917                         rsurface.svector3f_bufferobject = 0;
9918                         rsurface.svector3f_bufferoffset = 0;
9919                         rsurface.tvector3f = rsurface.array_deformedtvector3f;
9920                         rsurface.tvector3f_bufferobject = 0;
9921                         rsurface.tvector3f_bufferoffset = 0;
9922                         rsurface.normal3f = rsurface.array_deformednormal3f;
9923                         rsurface.normal3f_bufferobject = 0;
9924                         rsurface.normal3f_bufferoffset = 0;
9925                         break;
9926                 case Q3DEFORM_WAVE:
9927                         // deform vertex array to make wavey water and flags and such
9928                         waveparms[0] = deform->waveparms[0];
9929                         waveparms[1] = deform->waveparms[1];
9930                         waveparms[2] = deform->waveparms[2];
9931                         waveparms[3] = deform->waveparms[3];
9932                         // this is how a divisor of vertex influence on deformation
9933                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9934                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9935                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9936                         {
9937                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9938                                 for (j = 0;j < surface->num_vertices;j++)
9939                                 {
9940                                         float *vertex = (rsurface.array_deformedvertex3f  + 3 * surface->num_firstvertex) + j*3;
9941                                         VectorCopy((rsurface.vertex3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9942                                         // if the wavefunc depends on time, evaluate it per-vertex
9943                                         if (waveparms[3])
9944                                         {
9945                                                 waveparms[2] = deform->waveparms[2] + (vertex[0] + vertex[1] + vertex[2]) * animpos;
9946                                                 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9947                                         }
9948                                         VectorMA(vertex, scale, (rsurface.normal3f  + 3 * surface->num_firstvertex) + j*3, vertex);
9949                                 }
9950                         }
9951                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9952                         rsurface.vertex3f_bufferobject = 0;
9953                         rsurface.vertex3f_bufferoffset = 0;
9954                         break;
9955                 case Q3DEFORM_BULGE:
9956                         // deform vertex array to make the surface have moving bulges
9957                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9958                         {
9959                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9960                                 for (j = 0;j < surface->num_vertices;j++)
9961                                 {
9962                                         scale = sin((rsurface.modeltexcoordtexture2f[2 * (surface->num_firstvertex + j)] * deform->parms[0] + r_refdef.scene.time * deform->parms[2])) * deform->parms[1];
9963                                         VectorMA(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), scale, rsurface.normal3f + 3 * (surface->num_firstvertex + j), rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9964                                 }
9965                         }
9966                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9967                         rsurface.vertex3f_bufferobject = 0;
9968                         rsurface.vertex3f_bufferoffset = 0;
9969                         break;
9970                 case Q3DEFORM_MOVE:
9971                         // deform vertex array
9972                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9973                         VectorScale(deform->parms, scale, waveparms);
9974                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9975                         {
9976                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
9977                                 for (j = 0;j < surface->num_vertices;j++)
9978                                         VectorAdd(rsurface.vertex3f + 3 * (surface->num_firstvertex + j), waveparms, rsurface.array_deformedvertex3f + 3 * (surface->num_firstvertex + j));
9979                         }
9980                         rsurface.vertex3f = rsurface.array_deformedvertex3f;
9981                         rsurface.vertex3f_bufferobject = 0;
9982                         rsurface.vertex3f_bufferoffset = 0;
9983                         break;
9984                 }
9985         }
9986         // generate texcoords based on the chosen texcoord source
9987         switch(rsurface.texture->tcgen.tcgen)
9988         {
9989         default:
9990         case Q3TCGEN_TEXTURE:
9991                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordtexture2f;
9992                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordtexture2f_bufferobject;
9993                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9994                 break;
9995         case Q3TCGEN_LIGHTMAP:
9996                 rsurface.texcoordtexture2f               = rsurface.modeltexcoordlightmap2f;
9997                 rsurface.texcoordtexture2f_bufferobject  = rsurface.modeltexcoordlightmap2f_bufferobject;
9998                 rsurface.texcoordtexture2f_bufferoffset  = rsurface.modeltexcoordlightmap2f_bufferoffset;
9999                 break;
10000         case Q3TCGEN_VECTOR:
10001                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10002                 {
10003                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10004                         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)
10005                         {
10006                                 out_tc[0] = DotProduct(v1, rsurface.texture->tcgen.parms);
10007                                 out_tc[1] = DotProduct(v1, rsurface.texture->tcgen.parms + 3);
10008                         }
10009                 }
10010                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10011                 rsurface.texcoordtexture2f_bufferobject  = 0;
10012                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10013                 break;
10014         case Q3TCGEN_ENVIRONMENT:
10015                 // make environment reflections using a spheremap
10016                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10017                 {
10018                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10019                         const float *vertex = rsurface.modelvertex3f + 3 * surface->num_firstvertex;
10020                         const float *normal = rsurface.modelnormal3f + 3 * surface->num_firstvertex;
10021                         float *out_tc = rsurface.array_generatedtexcoordtexture2f + 2 * surface->num_firstvertex;
10022                         for (j = 0;j < surface->num_vertices;j++, vertex += 3, normal += 3, out_tc += 2)
10023                         {
10024                                 // identical to Q3A's method, but executed in worldspace so
10025                                 // carried models can be shiny too
10026
10027                                 float viewer[3], d, reflected[3], worldreflected[3];
10028
10029                                 VectorSubtract(rsurface.localvieworigin, vertex, viewer);
10030                                 // VectorNormalize(viewer);
10031
10032                                 d = DotProduct(normal, viewer);
10033
10034                                 reflected[0] = normal[0]*2*d - viewer[0];
10035                                 reflected[1] = normal[1]*2*d - viewer[1];
10036                                 reflected[2] = normal[2]*2*d - viewer[2];
10037                                 // note: this is proportinal to viewer, so we can normalize later
10038
10039                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10040                                 VectorNormalize(worldreflected);
10041
10042                                 // note: this sphere map only uses world x and z!
10043                                 // so positive and negative y will LOOK THE SAME.
10044                                 out_tc[0] = 0.5 + 0.5 * worldreflected[1];
10045                                 out_tc[1] = 0.5 - 0.5 * worldreflected[2];
10046                         }
10047                 }
10048                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10049                 rsurface.texcoordtexture2f_bufferobject  = 0;
10050                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10051                 break;
10052         }
10053         // the only tcmod that needs software vertex processing is turbulent, so
10054         // check for it here and apply the changes if needed
10055         // and we only support that as the first one
10056         // (handling a mixture of turbulent and other tcmods would be problematic
10057         //  without punting it entirely to a software path)
10058         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10059         {
10060                 amplitude = rsurface.texture->tcmods[0].parms[1];
10061                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10062                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10063                 {
10064                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10065                         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)
10066                         {
10067                                 out_tc[0] = in_tc[0] + amplitude * sin(((v1[0] + v1[2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10068                                 out_tc[1] = in_tc[1] + amplitude * sin(((v1[1]        ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10069                         }
10070                 }
10071                 rsurface.texcoordtexture2f               = rsurface.array_generatedtexcoordtexture2f;
10072                 rsurface.texcoordtexture2f_bufferobject  = 0;
10073                 rsurface.texcoordtexture2f_bufferoffset  = 0;
10074         }
10075         rsurface.texcoordlightmap2f              = rsurface.modeltexcoordlightmap2f;
10076         rsurface.texcoordlightmap2f_bufferobject = rsurface.modeltexcoordlightmap2f_bufferobject;
10077         rsurface.texcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10078         R_Mesh_VertexPointer(rsurface.vertex3f, rsurface.vertex3f_bufferobject, rsurface.vertex3f_bufferoffset);
10079 }
10080
10081 void RSurf_DrawBatch_Simple(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10082 {
10083         int i, j;
10084         const msurface_t *surface = texturesurfacelist[0];
10085         const msurface_t *surface2;
10086         int firstvertex;
10087         int endvertex;
10088         int numvertices;
10089         int numtriangles;
10090         // TODO: lock all array ranges before render, rather than on each surface
10091         if (texturenumsurfaces == 1)
10092                 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);
10093         else if (r_batchmode.integer == 2)
10094         {
10095                 #define MAXBATCHTRIANGLES 4096
10096                 int batchtriangles = 0;
10097                 static int batchelements[MAXBATCHTRIANGLES*3];
10098                 for (i = 0;i < texturenumsurfaces;i = j)
10099                 {
10100                         surface = texturesurfacelist[i];
10101                         j = i + 1;
10102                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10103                         {
10104                                 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);
10105                                 continue;
10106                         }
10107                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10108                         batchtriangles = surface->num_triangles;
10109                         firstvertex = surface->num_firstvertex;
10110                         endvertex = surface->num_firstvertex + surface->num_vertices;
10111                         for (;j < texturenumsurfaces;j++)
10112                         {
10113                                 surface2 = texturesurfacelist[j];
10114                                 if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10115                                         break;
10116                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10117                                 batchtriangles += surface2->num_triangles;
10118                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10119                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10120                         }
10121                         surface2 = texturesurfacelist[j-1];
10122                         numvertices = endvertex - firstvertex;
10123                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10124                 }
10125         }
10126         else if (r_batchmode.integer == 1)
10127         {
10128                 for (i = 0;i < texturenumsurfaces;i = j)
10129                 {
10130                         surface = texturesurfacelist[i];
10131                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10132                                 if (texturesurfacelist[j] != surface2)
10133                                         break;
10134                         surface2 = texturesurfacelist[j-1];
10135                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10136                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10137                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10138                 }
10139         }
10140         else
10141         {
10142                 for (i = 0;i < texturenumsurfaces;i++)
10143                 {
10144                         surface = texturesurfacelist[i];
10145                         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);
10146                 }
10147         }
10148 }
10149
10150 static void RSurf_BindLightmapForSurface(const msurface_t *surface)
10151 {
10152         switch(vid.renderpath)
10153         {
10154         case RENDERPATH_CGGL:
10155 #ifdef SUPPORTCG
10156                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , surface->lightmaptexture );CHECKCGERROR
10157                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, surface->deluxemaptexture);CHECKCGERROR
10158 #endif
10159                 break;
10160         case RENDERPATH_GL20:
10161                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , surface->lightmaptexture );
10162                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, surface->deluxemaptexture);
10163                 break;
10164         case RENDERPATH_GL13:
10165         case RENDERPATH_GL11:
10166                 R_Mesh_TexBind(0, surface->lightmaptexture);
10167                 break;
10168         }
10169 }
10170
10171 static void RSurf_BindReflectionForSurface(const msurface_t *surface)
10172 {
10173         // pick the closest matching water plane and bind textures
10174         int planeindex, vertexindex;
10175         float d, bestd;
10176         vec3_t vert;
10177         const float *v;
10178         r_waterstate_waterplane_t *p, *bestp;
10179         bestd = 0;
10180         bestp = NULL;
10181         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10182         {
10183                 d = 0;
10184                 for (vertexindex = 0, v = rsurface.modelvertex3f + surface->num_firstvertex * 3;vertexindex < surface->num_vertices;vertexindex++, v += 3)
10185                 {
10186                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10187                         d += fabs(PlaneDiff(vert, &p->plane));
10188                 }
10189                 if (bestd > d || !bestp)
10190                 {
10191                         bestd = d;
10192                         bestp = p;
10193                 }
10194         }
10195         switch(vid.renderpath)
10196         {
10197         case RENDERPATH_CGGL:
10198 #ifdef SUPPORTCG
10199                 if (r_cg_permutation->fp_Texture_Refraction) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR
10200                 if (r_cg_permutation->fp_Texture_Reflection) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR
10201 #endif
10202                 break;
10203         case RENDERPATH_GL20:
10204                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10205                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10206                 break;
10207         case RENDERPATH_GL13:
10208         case RENDERPATH_GL11:
10209                 break;
10210         }
10211 }
10212
10213 static void RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10214 {
10215         int i;
10216         const msurface_t *surface;
10217         if (r_waterstate.renderingscene)
10218                 return;
10219         for (i = 0;i < texturenumsurfaces;i++)
10220         {
10221                 surface = texturesurfacelist[i];
10222                 RSurf_BindLightmapForSurface(surface);
10223                 RSurf_BindReflectionForSurface(surface);
10224                 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);
10225         }
10226 }
10227
10228 static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10229 {
10230         int i;
10231         int j;
10232         const msurface_t *surface = texturesurfacelist[0];
10233         const msurface_t *surface2;
10234         int firstvertex;
10235         int endvertex;
10236         int numvertices;
10237         int numtriangles;
10238         if (texturenumsurfaces == 1)
10239         {
10240                 RSurf_BindLightmapForSurface(surface);
10241                 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);
10242         }
10243         else if (r_batchmode.integer == 2)
10244         {
10245 #define MAXBATCHTRIANGLES 4096
10246                 int batchtriangles = 0;
10247                 static int batchelements[MAXBATCHTRIANGLES*3];
10248                 for (i = 0;i < texturenumsurfaces;i = j)
10249                 {
10250                         surface = texturesurfacelist[i];
10251                         RSurf_BindLightmapForSurface(surface);
10252                         j = i + 1;
10253                         if (surface->num_triangles > MAXBATCHTRIANGLES)
10254                         {
10255                                 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);
10256                                 continue;
10257                         }
10258                         memcpy(batchelements, rsurface.modelelement3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
10259                         batchtriangles = surface->num_triangles;
10260                         firstvertex = surface->num_firstvertex;
10261                         endvertex = surface->num_firstvertex + surface->num_vertices;
10262                         for (;j < texturenumsurfaces;j++)
10263                         {
10264                                 surface2 = texturesurfacelist[j];
10265                                 if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
10266                                         break;
10267                                 memcpy(batchelements + batchtriangles * 3, rsurface.modelelement3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
10268                                 batchtriangles += surface2->num_triangles;
10269                                 firstvertex = min(firstvertex, surface2->num_firstvertex);
10270                                 endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
10271                         }
10272                         surface2 = texturesurfacelist[j-1];
10273                         numvertices = endvertex - firstvertex;
10274                         R_Mesh_Draw(firstvertex, numvertices, 0, batchtriangles, batchelements, NULL, 0, 0);
10275                 }
10276         }
10277         else if (r_batchmode.integer == 1)
10278         {
10279 #if 0
10280                 Con_Printf("%s batch sizes ignoring lightmap:", rsurface.texture->name);
10281                 for (i = 0;i < texturenumsurfaces;i = j)
10282                 {
10283                         surface = texturesurfacelist[i];
10284                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10285                                 if (texturesurfacelist[j] != surface2)
10286                                         break;
10287                         Con_Printf(" %i", j - i);
10288                 }
10289                 Con_Printf("\n");
10290                 Con_Printf("%s batch sizes honoring lightmap:", rsurface.texture->name);
10291 #endif
10292                 for (i = 0;i < texturenumsurfaces;i = j)
10293                 {
10294                         surface = texturesurfacelist[i];
10295                         RSurf_BindLightmapForSurface(surface);
10296                         for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
10297                                 if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
10298                                         break;
10299 #if 0
10300                         Con_Printf(" %i", j - i);
10301 #endif
10302                         surface2 = texturesurfacelist[j-1];
10303                         numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
10304                         numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
10305                         R_Mesh_Draw(surface->num_firstvertex, numvertices, surface->num_firsttriangle, numtriangles, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10306                 }
10307 #if 0
10308                 Con_Printf("\n");
10309 #endif
10310         }
10311         else
10312         {
10313                 for (i = 0;i < texturenumsurfaces;i++)
10314                 {
10315                         surface = texturesurfacelist[i];
10316                         RSurf_BindLightmapForSurface(surface);
10317                         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);
10318                 }
10319         }
10320 }
10321
10322 static void RSurf_DrawBatch_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10323 {
10324         int j;
10325         int texturesurfaceindex;
10326         if (r_showsurfaces.integer == 2)
10327         {
10328                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10329                 {
10330                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10331                         for (j = 0;j < surface->num_triangles;j++)
10332                         {
10333                                 float f = ((j + surface->num_firsttriangle) & 31) * (1.0f / 31.0f) * r_refdef.view.colorscale;
10334                                 GL_Color(f, f, f, 1);
10335                                 R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle + j, 1, rsurface.modelelement3i, rsurface.modelelement3s, rsurface.modelelement3i_bufferobject, rsurface.modelelement3s_bufferobject);
10336                         }
10337                 }
10338         }
10339         else
10340         {
10341                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10342                 {
10343                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10344                         int k = (int)(((size_t)surface) / sizeof(msurface_t));
10345                         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);
10346                         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);
10347                 }
10348         }
10349 }
10350
10351 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10352 {
10353         int texturesurfaceindex;
10354         int i;
10355         const float *v;
10356         float *c2;
10357         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10358         {
10359                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10360                 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)
10361                 {
10362                         c2[0] = 0.5;
10363                         c2[1] = 0.5;
10364                         c2[2] = 0.5;
10365                         c2[3] = 1;
10366                 }
10367         }
10368         rsurface.lightmapcolor4f = rsurface.array_color4f;
10369         rsurface.lightmapcolor4f_bufferobject = 0;
10370         rsurface.lightmapcolor4f_bufferoffset = 0;
10371 }
10372
10373 static void RSurf_DrawBatch_GL11_ApplyFog(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10374 {
10375         int texturesurfaceindex;
10376         int i;
10377         float f;
10378         const float *v;
10379         const float *c;
10380         float *c2;
10381         if (rsurface.lightmapcolor4f)
10382         {
10383                 // generate color arrays for the surfaces in this list
10384                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10385                 {
10386                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10387                         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)
10388                         {
10389                                 f = RSurf_FogVertex(v);
10390                                 c2[0] = c[0] * f;
10391                                 c2[1] = c[1] * f;
10392                                 c2[2] = c[2] * f;
10393                                 c2[3] = c[3];
10394                         }
10395                 }
10396         }
10397         else
10398         {
10399                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10400                 {
10401                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10402                         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)
10403                         {
10404                                 f = RSurf_FogVertex(v);
10405                                 c2[0] = f;
10406                                 c2[1] = f;
10407                                 c2[2] = f;
10408                                 c2[3] = 1;
10409                         }
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_ApplyFogToFinishedVertexColors(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10418 {
10419         int texturesurfaceindex;
10420         int i;
10421         float f;
10422         const float *v;
10423         const float *c;
10424         float *c2;
10425         if (!rsurface.lightmapcolor4f)
10426                 return;
10427         // generate color arrays for the surfaces in this list
10428         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10429         {
10430                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10431                 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)
10432                 {
10433                         f = RSurf_FogVertex(v);
10434                         c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10435                         c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10436                         c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10437                         c2[3] = c[3];
10438                 }
10439         }
10440         rsurface.lightmapcolor4f = rsurface.array_color4f;
10441         rsurface.lightmapcolor4f_bufferobject = 0;
10442         rsurface.lightmapcolor4f_bufferoffset = 0;
10443 }
10444
10445 static void RSurf_DrawBatch_GL11_ApplyColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a)
10446 {
10447         int texturesurfaceindex;
10448         int i;
10449         const float *c;
10450         float *c2;
10451         if (!rsurface.lightmapcolor4f)
10452                 return;
10453         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10454         {
10455                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10456                 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)
10457                 {
10458                         c2[0] = c[0] * r;
10459                         c2[1] = c[1] * g;
10460                         c2[2] = c[2] * b;
10461                         c2[3] = c[3] * a;
10462                 }
10463         }
10464         rsurface.lightmapcolor4f = rsurface.array_color4f;
10465         rsurface.lightmapcolor4f_bufferobject = 0;
10466         rsurface.lightmapcolor4f_bufferoffset = 0;
10467 }
10468
10469 static void RSurf_DrawBatch_GL11_ApplyAmbient(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10470 {
10471         int texturesurfaceindex;
10472         int i;
10473         const float *c;
10474         float *c2;
10475         if (!rsurface.lightmapcolor4f)
10476                 return;
10477         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10478         {
10479                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10480                 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)
10481                 {
10482                         c2[0] = c[0] + r_refdef.scene.ambient;
10483                         c2[1] = c[1] + r_refdef.scene.ambient;
10484                         c2[2] = c[2] + r_refdef.scene.ambient;
10485                         c2[3] = c[3];
10486                 }
10487         }
10488         rsurface.lightmapcolor4f = rsurface.array_color4f;
10489         rsurface.lightmapcolor4f_bufferobject = 0;
10490         rsurface.lightmapcolor4f_bufferoffset = 0;
10491 }
10492
10493 static void RSurf_DrawBatch_GL11_Lightmap(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10494 {
10495         // TODO: optimize
10496         rsurface.lightmapcolor4f = NULL;
10497         rsurface.lightmapcolor4f_bufferobject = 0;
10498         rsurface.lightmapcolor4f_bufferoffset = 0;
10499         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10500         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10501         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10502         GL_Color(r, g, b, a);
10503         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10504 }
10505
10506 static void RSurf_DrawBatch_GL11_Unlit(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10507 {
10508         // TODO: optimize applyfog && applycolor case
10509         // just apply fog if necessary, and tint the fog color array if necessary
10510         rsurface.lightmapcolor4f = NULL;
10511         rsurface.lightmapcolor4f_bufferobject = 0;
10512         rsurface.lightmapcolor4f_bufferoffset = 0;
10513         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10514         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10515         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10516         GL_Color(r, g, b, a);
10517         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10518 }
10519
10520 static void RSurf_DrawBatch_GL11_VertexColor(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10521 {
10522         int texturesurfaceindex;
10523         int i;
10524         float *c;
10525         // TODO: optimize
10526         if (texturesurfacelist[0]->lightmapinfo)
10527         {
10528                 // generate color arrays for the surfaces in this list
10529                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10530                 {
10531                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10532                         for (i = 0, c = rsurface.array_color4f + 4 * surface->num_firstvertex;i < surface->num_vertices;i++, c += 4)
10533                         {
10534                                 if (surface->lightmapinfo->samples)
10535                                 {
10536                                         const unsigned char *lm = surface->lightmapinfo->samples + (rsurface.modellightmapoffsets + surface->num_firstvertex)[i];
10537                                         float scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]] * (1.0f / 32768.0f);
10538                                         VectorScale(lm, scale, c);
10539                                         if (surface->lightmapinfo->styles[1] != 255)
10540                                         {
10541                                                 int size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10542                                                 lm += size3;
10543                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]] * (1.0f / 32768.0f);
10544                                                 VectorMA(c, scale, lm, c);
10545                                                 if (surface->lightmapinfo->styles[2] != 255)
10546                                                 {
10547                                                         lm += size3;
10548                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]] * (1.0f / 32768.0f);
10549                                                         VectorMA(c, scale, lm, c);
10550                                                         if (surface->lightmapinfo->styles[3] != 255)
10551                                                         {
10552                                                                 lm += size3;
10553                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]] * (1.0f / 32768.0f);
10554                                                                 VectorMA(c, scale, lm, c);
10555                                                         }
10556                                                 }
10557                                         }
10558                                 }
10559                                 else
10560                                         VectorClear(c);
10561                                 c[3] = 1;
10562                         }
10563                 }
10564                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10565                 rsurface.lightmapcolor4f_bufferobject = 0;
10566                 rsurface.lightmapcolor4f_bufferoffset = 0;
10567         }
10568         else
10569         {
10570                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
10571                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
10572                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
10573         }
10574         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10575         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10576         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10577         GL_Color(r, g, b, a);
10578         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10579 }
10580
10581 static void RSurf_DrawBatch_GL11_ApplyVertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float *r, float *g, float *b, float *a, qboolean *applycolor)
10582 {
10583         int texturesurfaceindex;
10584         int i;
10585         float f;
10586         float alpha;
10587         const float *v;
10588         const float *n;
10589         float *c;
10590         vec3_t ambientcolor;
10591         vec3_t diffusecolor;
10592         vec3_t lightdir;
10593         // TODO: optimize
10594         // model lighting
10595         VectorCopy(rsurface.modellight_lightdir, lightdir);
10596         f = 0.5f * r_refdef.lightmapintensity;
10597         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10598         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10599         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10600         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10601         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10602         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10603         alpha = *a;
10604         if (VectorLength2(diffusecolor) > 0 && rsurface.normal3f)
10605         {
10606                 // generate color arrays for the surfaces in this list
10607                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10608                 {
10609                         const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10610                         int numverts = surface->num_vertices;
10611                         v = rsurface.vertex3f + 3 * surface->num_firstvertex;
10612                         n = rsurface.normal3f + 3 * surface->num_firstvertex;
10613                         c = rsurface.array_color4f + 4 * surface->num_firstvertex;
10614                         // q3-style directional shading
10615                         for (i = 0;i < numverts;i++, v += 3, n += 3, c += 4)
10616                         {
10617                                 if ((f = DotProduct(n, lightdir)) > 0)
10618                                         VectorMA(ambientcolor, f, diffusecolor, c);
10619                                 else
10620                                         VectorCopy(ambientcolor, c);
10621                                 c[3] = alpha;
10622                         }
10623                 }
10624                 *r = 1;
10625                 *g = 1;
10626                 *b = 1;
10627                 *a = 1;
10628                 rsurface.lightmapcolor4f = rsurface.array_color4f;
10629                 rsurface.lightmapcolor4f_bufferobject = 0;
10630                 rsurface.lightmapcolor4f_bufferoffset = 0;
10631                 *applycolor = false;
10632         }
10633         else
10634         {
10635                 *r = ambientcolor[0];
10636                 *g = ambientcolor[1];
10637                 *b = ambientcolor[2];
10638                 rsurface.lightmapcolor4f = NULL;
10639                 rsurface.lightmapcolor4f_bufferobject = 0;
10640                 rsurface.lightmapcolor4f_bufferoffset = 0;
10641         }
10642 }
10643
10644 static void RSurf_DrawBatch_GL11_VertexShade(int texturenumsurfaces, const msurface_t **texturesurfacelist, float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10645 {
10646         RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &r, &g, &b, &a, &applycolor);
10647         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog(texturenumsurfaces, texturesurfacelist);
10648         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, r, g, b, a);
10649         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
10650         GL_Color(r, g, b, a);
10651         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10652 }
10653
10654 void RSurf_SetupDepthAndCulling(void)
10655 {
10656         // submodels are biased to avoid z-fighting with world surfaces that they
10657         // may be exactly overlapping (avoids z-fighting artifacts on certain
10658         // doors and things in Quake maps)
10659         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10660         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10661         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10662         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10663 }
10664
10665 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10666 {
10667         // transparent sky would be ridiculous
10668         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10669                 return;
10670         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10671         skyrenderlater = true;
10672         RSurf_SetupDepthAndCulling();
10673         GL_DepthMask(true);
10674         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10675         // skymasking on them, and Quake3 never did sky masking (unlike
10676         // software Quake and software Quake2), so disable the sky masking
10677         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10678         // and skymasking also looks very bad when noclipping outside the
10679         // level, so don't use it then either.
10680         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
10681         {
10682                 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10683                 R_Mesh_ColorPointer(NULL, 0, 0);
10684                 R_Mesh_ResetTextureState();
10685                 if (skyrendermasked)
10686                 {
10687                         R_SetupShader_DepthOrShadow();
10688                         // depth-only (masking)
10689                         GL_ColorMask(0,0,0,0);
10690                         // just to make sure that braindead drivers don't draw
10691                         // anything despite that colormask...
10692                         GL_BlendFunc(GL_ZERO, GL_ONE);
10693                 }
10694                 else
10695                 {
10696                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10697                         // fog sky
10698                         GL_BlendFunc(GL_ONE, GL_ZERO);
10699                 }
10700                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
10701                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10702                 if (skyrendermasked)
10703                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10704         }
10705         R_Mesh_ResetTextureState();
10706         GL_Color(1, 1, 1, 1);
10707 }
10708
10709 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10710 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10711 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10712 {
10713         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION)))
10714                 return;
10715         RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
10716         if (prepass)
10717         {
10718                 // render screenspace normalmap to texture
10719                 GL_DepthMask(true);
10720                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY);
10721                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10722         }
10723         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION)) && !r_waterstate.renderingscene)
10724         {
10725                 // render water or distortion background, then blend surface on top
10726                 GL_DepthMask(true);
10727                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND);
10728                 RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10729                 GL_DepthMask(false);
10730                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10731                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10732                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10733                 else
10734                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10735         }
10736         else
10737         {
10738                 // render surface normally
10739                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10740                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE);
10741                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
10742                         RSurf_DrawBatch_WithLightmapSwitching_WithWaterTextureSwitching(texturenumsurfaces, texturesurfacelist);
10743                 else if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10744                         RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist);
10745                 else
10746                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10747         }
10748 }
10749
10750 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10751 {
10752         // OpenGL 1.3 path - anything not completely ancient
10753         int texturesurfaceindex;
10754         qboolean applycolor;
10755         qboolean applyfog;
10756         int layerindex;
10757         const texturelayer_t *layer;
10758         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10759
10760         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10761         {
10762                 vec4_t layercolor;
10763                 int layertexrgbscale;
10764                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10765                 {
10766                         if (layerindex == 0)
10767                                 GL_AlphaTest(true);
10768                         else
10769                         {
10770                                 GL_AlphaTest(false);
10771                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10772                         }
10773                 }
10774                 GL_DepthMask(layer->depthmask && writedepth);
10775                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10776                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10777                 {
10778                         layertexrgbscale = 4;
10779                         VectorScale(layer->color, 0.25f, layercolor);
10780                 }
10781                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10782                 {
10783                         layertexrgbscale = 2;
10784                         VectorScale(layer->color, 0.5f, layercolor);
10785                 }
10786                 else
10787                 {
10788                         layertexrgbscale = 1;
10789                         VectorScale(layer->color, 1.0f, layercolor);
10790                 }
10791                 layercolor[3] = layer->color[3];
10792                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10793                 R_Mesh_ColorPointer(NULL, 0, 0);
10794                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10795                 switch (layer->type)
10796                 {
10797                 case TEXTURELAYERTYPE_LITTEXTURE:
10798                         // single-pass lightmapped texture with 2x rgbscale
10799                         R_Mesh_TexBind(0, r_texture_white);
10800                         R_Mesh_TexMatrix(0, NULL);
10801                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10802                         R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10803                         R_Mesh_TexBind(1, layer->texture);
10804                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10805                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10806                         R_Mesh_TexCoordPointer(1, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10807                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10808                                 RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10809                         else if (rsurface.uselightmaptexture)
10810                                 RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10811                         else
10812                                 RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10813                         break;
10814                 case TEXTURELAYERTYPE_TEXTURE:
10815                         // singletexture unlit texture with transparency support
10816                         R_Mesh_TexBind(0, layer->texture);
10817                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10818                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10819                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10820                         R_Mesh_TexBind(1, 0);
10821                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10822                         RSurf_DrawBatch_GL11_Unlit(texturenumsurfaces, texturesurfacelist, layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10823                         break;
10824                 case TEXTURELAYERTYPE_FOG:
10825                         // singletexture fogging
10826                         if (layer->texture)
10827                         {
10828                                 R_Mesh_TexBind(0, layer->texture);
10829                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10830                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10831                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10832                         }
10833                         else
10834                         {
10835                                 R_Mesh_TexBind(0, 0);
10836                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10837                         }
10838                         R_Mesh_TexBind(1, 0);
10839                         R_Mesh_TexCoordPointer(1, 2, NULL, 0, 0);
10840                         // generate a color array for the fog pass
10841                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10842                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10843                         {
10844                                 int i;
10845                                 float f;
10846                                 const float *v;
10847                                 float *c;
10848                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10849                                 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)
10850                                 {
10851                                         f = 1 - RSurf_FogVertex(v);
10852                                         c[0] = layercolor[0];
10853                                         c[1] = layercolor[1];
10854                                         c[2] = layercolor[2];
10855                                         c[3] = f * layercolor[3];
10856                                 }
10857                         }
10858                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10859                         break;
10860                 default:
10861                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10862                 }
10863         }
10864         CHECKGLERROR
10865         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10866         {
10867                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10868                 GL_AlphaTest(false);
10869         }
10870 }
10871
10872 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10873 {
10874         // OpenGL 1.1 - crusty old voodoo path
10875         int texturesurfaceindex;
10876         qboolean applyfog;
10877         int layerindex;
10878         const texturelayer_t *layer;
10879         RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
10880
10881         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10882         {
10883                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10884                 {
10885                         if (layerindex == 0)
10886                                 GL_AlphaTest(true);
10887                         else
10888                         {
10889                                 GL_AlphaTest(false);
10890                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
10891                         }
10892                 }
10893                 GL_DepthMask(layer->depthmask && writedepth);
10894                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10895                 R_Mesh_ColorPointer(NULL, 0, 0);
10896                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10897                 switch (layer->type)
10898                 {
10899                 case TEXTURELAYERTYPE_LITTEXTURE:
10900                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10901                         {
10902                                 // two-pass lit texture with 2x rgbscale
10903                                 // first the lightmap pass
10904                                 R_Mesh_TexBind(0, r_texture_white);
10905                                 R_Mesh_TexMatrix(0, NULL);
10906                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10907                                 R_Mesh_TexCoordPointer(0, 2, rsurface.modeltexcoordlightmap2f, rsurface.modeltexcoordlightmap2f_bufferobject, rsurface.modeltexcoordlightmap2f_bufferoffset);
10908                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10909                                         RSurf_DrawBatch_GL11_VertexShade(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10910                                 else if (rsurface.uselightmaptexture)
10911                                         RSurf_DrawBatch_GL11_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10912                                 else
10913                                         RSurf_DrawBatch_GL11_VertexColor(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, false, false);
10914                                 // then apply the texture to it
10915                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10916                                 R_Mesh_TexBind(0, layer->texture);
10917                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10918                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10919                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10920                                 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);
10921                         }
10922                         else
10923                         {
10924                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10925                                 R_Mesh_TexBind(0, layer->texture);
10926                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10927                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10928                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10929                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10930                                         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);
10931                                 else
10932                                         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);
10933                         }
10934                         break;
10935                 case TEXTURELAYERTYPE_TEXTURE:
10936                         // singletexture unlit texture with transparency support
10937                         R_Mesh_TexBind(0, layer->texture);
10938                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10939                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10940                         R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10941                         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);
10942                         break;
10943                 case TEXTURELAYERTYPE_FOG:
10944                         // singletexture fogging
10945                         if (layer->texture)
10946                         {
10947                                 R_Mesh_TexBind(0, layer->texture);
10948                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10949                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10950                                 R_Mesh_TexCoordPointer(0, 2, rsurface.texcoordtexture2f, rsurface.texcoordtexture2f_bufferobject, rsurface.texcoordtexture2f_bufferoffset);
10951                         }
10952                         else
10953                         {
10954                                 R_Mesh_TexBind(0, 0);
10955                                 R_Mesh_TexCoordPointer(0, 2, NULL, 0, 0);
10956                         }
10957                         // generate a color array for the fog pass
10958                         R_Mesh_ColorPointer(rsurface.array_color4f, 0, 0);
10959                         for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10960                         {
10961                                 int i;
10962                                 float f;
10963                                 const float *v;
10964                                 float *c;
10965                                 const msurface_t *surface = texturesurfacelist[texturesurfaceindex];
10966                                 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)
10967                                 {
10968                                         f = 1 - RSurf_FogVertex(v);
10969                                         c[0] = layer->color[0];
10970                                         c[1] = layer->color[1];
10971                                         c[2] = layer->color[2];
10972                                         c[3] = f * layer->color[3];
10973                                 }
10974                         }
10975                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
10976                         break;
10977                 default:
10978                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10979                 }
10980         }
10981         CHECKGLERROR
10982         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10983         {
10984                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
10985                 GL_AlphaTest(false);
10986         }
10987 }
10988
10989 static void R_DrawTextureSurfaceList_ShowSurfaces3(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10990 {
10991         float c[4];
10992
10993         GL_AlphaTest(false);
10994         R_Mesh_ColorPointer(NULL, 0, 0);
10995         R_Mesh_ResetTextureState();
10996         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10997
10998         if(rsurface.texture && rsurface.texture->currentskinframe)
10999         {
11000                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11001                 c[3] *= rsurface.texture->currentalpha;
11002         }
11003         else
11004         {
11005                 c[0] = 1;
11006                 c[1] = 0;
11007                 c[2] = 1;
11008                 c[3] = 1;
11009         }
11010
11011         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11012         {
11013                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11014                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11015                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11016         }
11017
11018         // brighten it up (as texture value 127 means "unlit")
11019         c[0] *= 2 * r_refdef.view.colorscale;
11020         c[1] *= 2 * r_refdef.view.colorscale;
11021         c[2] *= 2 * r_refdef.view.colorscale;
11022
11023         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11024                 c[3] *= r_wateralpha.value;
11025
11026         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11027         {
11028                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11029                 GL_DepthMask(false);
11030         }
11031         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11032         {
11033                 GL_BlendFunc(GL_ONE, GL_ONE);
11034                 GL_DepthMask(false);
11035         }
11036         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11037         {
11038                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11039                 GL_DepthMask(false);
11040         }
11041         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11042         {
11043                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11044                 GL_DepthMask(false);
11045         }
11046         else
11047         {
11048                 GL_BlendFunc(GL_ONE, GL_ZERO);
11049                 GL_DepthMask(writedepth);
11050         }
11051
11052         rsurface.lightmapcolor4f = NULL;
11053
11054         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11055         {
11056                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11057
11058                 rsurface.lightmapcolor4f = NULL;
11059                 rsurface.lightmapcolor4f_bufferobject = 0;
11060                 rsurface.lightmapcolor4f_bufferoffset = 0;
11061         }
11062         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11063         {
11064                 qboolean applycolor = true;
11065                 float one = 1.0;
11066
11067                 RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
11068
11069                 r_refdef.lightmapintensity = 1;
11070                 RSurf_DrawBatch_GL11_ApplyVertexShade(texturenumsurfaces, texturesurfacelist, &one, &one, &one, &one, &applycolor);
11071                 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11072         }
11073         else
11074         {
11075                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11076
11077                 rsurface.lightmapcolor4f = rsurface.modellightmapcolor4f;
11078                 rsurface.lightmapcolor4f_bufferobject = rsurface.modellightmapcolor4f_bufferobject;
11079                 rsurface.lightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
11080         }
11081
11082         if(!rsurface.lightmapcolor4f)
11083                 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(texturenumsurfaces, texturesurfacelist);
11084
11085         RSurf_DrawBatch_GL11_ApplyAmbient(texturenumsurfaces, texturesurfacelist);
11086         RSurf_DrawBatch_GL11_ApplyColor(texturenumsurfaces, texturesurfacelist, c[0], c[1], c[2], c[3]);
11087         if(r_refdef.fogenabled)
11088                 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(texturenumsurfaces, texturesurfacelist);
11089
11090         R_Mesh_ColorPointer(rsurface.lightmapcolor4f, rsurface.lightmapcolor4f_bufferobject, rsurface.lightmapcolor4f_bufferoffset);
11091         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11092 }
11093
11094 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11095 {
11096         CHECKGLERROR
11097         RSurf_SetupDepthAndCulling();
11098         if (r_showsurfaces.integer == 3 && !prepass && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11099         {
11100                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11101                 return;
11102         }
11103         switch (vid.renderpath)
11104         {
11105         case RENDERPATH_GL20:
11106         case RENDERPATH_CGGL:
11107                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11108                 break;
11109         case RENDERPATH_GL13:
11110                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11111                 break;
11112         case RENDERPATH_GL11:
11113                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11114                 break;
11115         }
11116         CHECKGLERROR
11117 }
11118
11119 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11120 {
11121         CHECKGLERROR
11122         RSurf_SetupDepthAndCulling();
11123         if (r_showsurfaces.integer == 3 && !prepass && (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY))
11124         {
11125                 R_DrawTextureSurfaceList_ShowSurfaces3(texturenumsurfaces, texturesurfacelist, writedepth);
11126                 return;
11127         }
11128         switch (vid.renderpath)
11129         {
11130         case RENDERPATH_GL20:
11131         case RENDERPATH_CGGL:
11132                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11133                 break;
11134         case RENDERPATH_GL13:
11135                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11136                 break;
11137         case RENDERPATH_GL11:
11138                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11139                 break;
11140         }
11141         CHECKGLERROR
11142 }
11143
11144 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11145 {
11146         int i, j;
11147         int texturenumsurfaces, endsurface;
11148         texture_t *texture;
11149         const msurface_t *surface;
11150         const msurface_t *texturesurfacelist[256];
11151
11152         // if the model is static it doesn't matter what value we give for
11153         // wantnormals and wanttangents, so this logic uses only rules applicable
11154         // to a model, knowing that they are meaningless otherwise
11155         if (ent == r_refdef.scene.worldentity)
11156                 RSurf_ActiveWorldEntity();
11157         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11158                 RSurf_ActiveModelEntity(ent, false, false, false);
11159         else
11160         {
11161                 switch (vid.renderpath)
11162                 {
11163                 case RENDERPATH_GL20:
11164                 case RENDERPATH_CGGL:
11165                         RSurf_ActiveModelEntity(ent, true, true, false);
11166                         break;
11167                 case RENDERPATH_GL13:
11168                 case RENDERPATH_GL11:
11169                         RSurf_ActiveModelEntity(ent, true, false, false);
11170                         break;
11171                 }
11172         }
11173
11174         if (r_transparentdepthmasking.integer)
11175         {
11176                 qboolean setup = false;
11177                 for (i = 0;i < numsurfaces;i = j)
11178                 {
11179                         j = i + 1;
11180                         surface = rsurface.modelsurfaces + surfacelist[i];
11181                         texture = surface->texture;
11182                         rsurface.texture = R_GetCurrentTexture(texture);
11183                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11184                         // scan ahead until we find a different texture
11185                         endsurface = min(i + 1024, numsurfaces);
11186                         texturenumsurfaces = 0;
11187                         texturesurfacelist[texturenumsurfaces++] = surface;
11188                         for (;j < endsurface;j++)
11189                         {
11190                                 surface = rsurface.modelsurfaces + surfacelist[j];
11191                                 if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11192                                         break;
11193                                 texturesurfacelist[texturenumsurfaces++] = surface;
11194                         }
11195                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11196                                 continue;
11197                         // render the range of surfaces as depth
11198                         if (!setup)
11199                         {
11200                                 setup = true;
11201                                 GL_ColorMask(0,0,0,0);
11202                                 GL_Color(1,1,1,1);
11203                                 GL_DepthTest(true);
11204                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11205                                 GL_DepthMask(true);
11206                                 GL_AlphaTest(false);
11207                                 R_Mesh_ColorPointer(NULL, 0, 0);
11208                                 R_Mesh_ResetTextureState();
11209                                 R_SetupShader_DepthOrShadow();
11210                         }
11211                         RSurf_SetupDepthAndCulling();
11212                         RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11213                         RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11214                 }
11215                 if (setup)
11216                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11217         }
11218
11219         for (i = 0;i < numsurfaces;i = j)
11220         {
11221                 j = i + 1;
11222                 surface = rsurface.modelsurfaces + surfacelist[i];
11223                 texture = surface->texture;
11224                 rsurface.texture = R_GetCurrentTexture(texture);
11225                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11226                 // scan ahead until we find a different texture
11227                 endsurface = min(i + 1024, numsurfaces);
11228                 texturenumsurfaces = 0;
11229                 texturesurfacelist[texturenumsurfaces++] = surface;
11230                 for (;j < endsurface;j++)
11231                 {
11232                         surface = rsurface.modelsurfaces + surfacelist[j];
11233                         if (texture != surface->texture || rsurface.uselightmaptexture != (surface->lightmaptexture != NULL))
11234                                 break;
11235                         texturesurfacelist[texturenumsurfaces++] = surface;
11236                 }
11237                 // render the range of surfaces
11238                 if (ent == r_refdef.scene.worldentity)
11239                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11240                 else
11241                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11242         }
11243         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11244         GL_AlphaTest(false);
11245 }
11246
11247 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11248 {
11249         // transparent surfaces get pushed off into the transparent queue
11250         int surfacelistindex;
11251         const msurface_t *surface;
11252         vec3_t tempcenter, center;
11253         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11254         {
11255                 surface = texturesurfacelist[surfacelistindex];
11256                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11257                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11258                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11259                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11260                 if (queueentity->transparent_offset) // transparent offset
11261                 {
11262                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11263                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11264                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11265                 }
11266                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11267         }
11268 }
11269
11270 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11271 {
11272         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11273         CHECKGLERROR
11274         if (depthonly)
11275         {
11276                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11277                         return;
11278                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11279                         return;
11280                 RSurf_SetupDepthAndCulling();
11281                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11282                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11283         }
11284         else if (prepass)
11285         {
11286                 if (!rsurface.texture->currentnumlayers)
11287                         return;
11288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11289                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11290                 else
11291                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11292         }
11293         else if (r_showsurfaces.integer && !r_refdef.view.showdebug && !prepass)
11294         {
11295                 RSurf_SetupDepthAndCulling();
11296                 GL_AlphaTest(false);
11297                 R_Mesh_ColorPointer(NULL, 0, 0);
11298                 R_Mesh_ResetTextureState();
11299                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11300                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11301                 GL_DepthMask(true);
11302                 GL_BlendFunc(GL_ONE, GL_ZERO);
11303                 GL_Color(0, 0, 0, 1);
11304                 GL_DepthTest(writedepth);
11305                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11306         }
11307         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3 && !prepass)
11308         {
11309                 RSurf_SetupDepthAndCulling();
11310                 GL_AlphaTest(false);
11311                 R_Mesh_ColorPointer(NULL, 0, 0);
11312                 R_Mesh_ResetTextureState();
11313                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11314                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11315                 GL_DepthMask(true);
11316                 GL_BlendFunc(GL_ONE, GL_ZERO);
11317                 GL_DepthTest(true);
11318                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11319         }
11320         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11321                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11322         else if (!rsurface.texture->currentnumlayers)
11323                 return;
11324         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11325         {
11326                 // in the deferred case, transparent surfaces were queued during prepass
11327                 if (!r_shadow_usingdeferredprepass)
11328                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11329         }
11330         else
11331         {
11332                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11333                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11334         }
11335         CHECKGLERROR
11336 }
11337
11338 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11339 {
11340         int i, j;
11341         texture_t *texture;
11342         // break the surface list down into batches by texture and use of lightmapping
11343         for (i = 0;i < numsurfaces;i = j)
11344         {
11345                 j = i + 1;
11346                 // texture is the base texture pointer, rsurface.texture is the
11347                 // current frame/skin the texture is directing us to use (for example
11348                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11349                 // use skin 1 instead)
11350                 texture = surfacelist[i]->texture;
11351                 rsurface.texture = R_GetCurrentTexture(texture);
11352                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11353                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11354                 {
11355                         // if this texture is not the kind we want, skip ahead to the next one
11356                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11357                                 ;
11358                         continue;
11359                 }
11360                 // simply scan ahead until we find a different texture or lightmap state
11361                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11362                         ;
11363                 // render the range of surfaces
11364                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11365         }
11366 }
11367
11368 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11369 {
11370         CHECKGLERROR
11371         if (depthonly)
11372         {
11373                 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11374                         return;
11375                 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11376                         return;
11377                 RSurf_SetupDepthAndCulling();
11378                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11379                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11380         }
11381         else if (prepass)
11382         {
11383                 if (!rsurface.texture->currentnumlayers)
11384                         return;
11385                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11386                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11387                 else
11388                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11389         }
11390         else if (r_showsurfaces.integer && !r_refdef.view.showdebug)
11391         {
11392                 RSurf_SetupDepthAndCulling();
11393                 GL_AlphaTest(false);
11394                 R_Mesh_ColorPointer(NULL, 0, 0);
11395                 R_Mesh_ResetTextureState();
11396                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11397                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11398                 GL_DepthMask(true);
11399                 GL_BlendFunc(GL_ONE, GL_ZERO);
11400                 GL_Color(0, 0, 0, 1);
11401                 GL_DepthTest(writedepth);
11402                 RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
11403         }
11404         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11405         {
11406                 RSurf_SetupDepthAndCulling();
11407                 GL_AlphaTest(false);
11408                 R_Mesh_ColorPointer(NULL, 0, 0);
11409                 R_Mesh_ResetTextureState();
11410                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11411                 RSurf_PrepareVerticesForBatch(false, false, texturenumsurfaces, texturesurfacelist);
11412                 GL_DepthMask(true);
11413                 GL_BlendFunc(GL_ONE, GL_ZERO);
11414                 GL_DepthTest(true);
11415                 RSurf_DrawBatch_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
11416         }
11417         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY)
11418                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11419         else if (!rsurface.texture->currentnumlayers)
11420                 return;
11421         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11422         {
11423                 // in the deferred case, transparent surfaces were queued during prepass
11424                 if (!r_shadow_usingdeferredprepass)
11425                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11426         }
11427         else
11428         {
11429                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11430                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11431         }
11432         CHECKGLERROR
11433 }
11434
11435 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11436 {
11437         int i, j;
11438         texture_t *texture;
11439         // break the surface list down into batches by texture and use of lightmapping
11440         for (i = 0;i < numsurfaces;i = j)
11441         {
11442                 j = i + 1;
11443                 // texture is the base texture pointer, rsurface.texture is the
11444                 // current frame/skin the texture is directing us to use (for example
11445                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11446                 // use skin 1 instead)
11447                 texture = surfacelist[i]->texture;
11448                 rsurface.texture = R_GetCurrentTexture(texture);
11449                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11450                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11451                 {
11452                         // if this texture is not the kind we want, skip ahead to the next one
11453                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11454                                 ;
11455                         continue;
11456                 }
11457                 // simply scan ahead until we find a different texture or lightmap state
11458                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.uselightmaptexture == (surfacelist[j]->lightmaptexture != NULL);j++)
11459                         ;
11460                 // render the range of surfaces
11461                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11462         }
11463 }
11464
11465 float locboxvertex3f[6*4*3] =
11466 {
11467         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11468         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11469         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11470         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11471         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11472         1,0,0, 0,0,0, 0,1,0, 1,1,0
11473 };
11474
11475 unsigned short locboxelements[6*2*3] =
11476 {
11477          0, 1, 2, 0, 2, 3,
11478          4, 5, 6, 4, 6, 7,
11479          8, 9,10, 8,10,11,
11480         12,13,14, 12,14,15,
11481         16,17,18, 16,18,19,
11482         20,21,22, 20,22,23
11483 };
11484
11485 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11486 {
11487         int i, j;
11488         cl_locnode_t *loc = (cl_locnode_t *)ent;
11489         vec3_t mins, size;
11490         float vertex3f[6*4*3];
11491         CHECKGLERROR
11492         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11493         GL_DepthMask(false);
11494         GL_DepthRange(0, 1);
11495         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11496         GL_DepthTest(true);
11497         GL_CullFace(GL_NONE);
11498         R_EntityMatrix(&identitymatrix);
11499
11500         R_Mesh_VertexPointer(vertex3f, 0, 0);
11501         R_Mesh_ColorPointer(NULL, 0, 0);
11502         R_Mesh_ResetTextureState();
11503         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11504
11505         i = surfacelist[0];
11506         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11507                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11508                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11509                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11510
11511         if (VectorCompare(loc->mins, loc->maxs))
11512         {
11513                 VectorSet(size, 2, 2, 2);
11514                 VectorMA(loc->mins, -0.5f, size, mins);
11515         }
11516         else
11517         {
11518                 VectorCopy(loc->mins, mins);
11519                 VectorSubtract(loc->maxs, loc->mins, size);
11520         }
11521
11522         for (i = 0;i < 6*4*3;)
11523                 for (j = 0;j < 3;j++, i++)
11524                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11525
11526         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, locboxelements, 0, 0);
11527 }
11528
11529 void R_DrawLocs(void)
11530 {
11531         int index;
11532         cl_locnode_t *loc, *nearestloc;
11533         vec3_t center;
11534         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11535         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11536         {
11537                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11538                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11539         }
11540 }
11541
11542 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11543 {
11544         if (decalsystem->decals)
11545                 Mem_Free(decalsystem->decals);
11546         memset(decalsystem, 0, sizeof(*decalsystem));
11547 }
11548
11549 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)
11550 {
11551         tridecal_t *decal;
11552         tridecal_t *decals;
11553         int i;
11554
11555         // expand or initialize the system
11556         if (decalsystem->maxdecals <= decalsystem->numdecals)
11557         {
11558                 decalsystem_t old = *decalsystem;
11559                 qboolean useshortelements;
11560                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11561                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11562                 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)));
11563                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11564                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11565                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11566                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11567                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11568                 if (decalsystem->numdecals)
11569                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11570                 if (old.decals)
11571                         Mem_Free(old.decals);
11572                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11573                         decalsystem->element3i[i] = i;
11574                 if (useshortelements)
11575                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11576                                 decalsystem->element3s[i] = i;
11577         }
11578
11579         // grab a decal and search for another free slot for the next one
11580         decals = decalsystem->decals;
11581         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11582         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
11583                 ;
11584         decalsystem->freedecal = i;
11585         if (decalsystem->numdecals <= i)
11586                 decalsystem->numdecals = i + 1;
11587
11588         // initialize the decal
11589         decal->lived = 0;
11590         decal->triangleindex = triangleindex;
11591         decal->surfaceindex = surfaceindex;
11592         decal->decalsequence = decalsequence;
11593         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
11594         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
11595         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
11596         decal->color4ub[0][3] = 255;
11597         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
11598         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
11599         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
11600         decal->color4ub[1][3] = 255;
11601         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
11602         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
11603         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
11604         decal->color4ub[2][3] = 255;
11605         decal->vertex3f[0][0] = v0[0];
11606         decal->vertex3f[0][1] = v0[1];
11607         decal->vertex3f[0][2] = v0[2];
11608         decal->vertex3f[1][0] = v1[0];
11609         decal->vertex3f[1][1] = v1[1];
11610         decal->vertex3f[1][2] = v1[2];
11611         decal->vertex3f[2][0] = v2[0];
11612         decal->vertex3f[2][1] = v2[1];
11613         decal->vertex3f[2][2] = v2[2];
11614         decal->texcoord2f[0][0] = t0[0];
11615         decal->texcoord2f[0][1] = t0[1];
11616         decal->texcoord2f[1][0] = t1[0];
11617         decal->texcoord2f[1][1] = t1[1];
11618         decal->texcoord2f[2][0] = t2[0];
11619         decal->texcoord2f[2][1] = t2[1];
11620 }
11621
11622 extern cvar_t cl_decals_bias;
11623 extern cvar_t cl_decals_models;
11624 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11625 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)
11626 {
11627         matrix4x4_t projection;
11628         decalsystem_t *decalsystem;
11629         qboolean dynamic;
11630         dp_model_t *model;
11631         const float *vertex3f;
11632         const msurface_t *surface;
11633         const msurface_t *surfaces;
11634         const int *surfacelist;
11635         const texture_t *texture;
11636         int numtriangles;
11637         int numsurfacelist;
11638         int surfacelistindex;
11639         int surfaceindex;
11640         int triangleindex;
11641         int cornerindex;
11642         int index;
11643         int numpoints;
11644         const int *e;
11645         float localorigin[3];
11646         float localnormal[3];
11647         float localmins[3];
11648         float localmaxs[3];
11649         float localsize;
11650         float v[9][3];
11651         float tc[9][2];
11652         float c[9][4];
11653         //float normal[3];
11654         float planes[6][4];
11655         float f;
11656         float points[2][9][3];
11657         float angles[3];
11658         float temp[3];
11659
11660         decalsystem = &ent->decalsystem;
11661         model = ent->model;
11662         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11663         {
11664                 R_DecalSystem_Reset(&ent->decalsystem);
11665                 return;
11666         }
11667
11668         if (!model->brush.data_nodes && !cl_decals_models.integer)
11669         {
11670                 if (decalsystem->model)
11671                         R_DecalSystem_Reset(decalsystem);
11672                 return;
11673         }
11674
11675         if (decalsystem->model != model)
11676                 R_DecalSystem_Reset(decalsystem);
11677         decalsystem->model = model;
11678
11679         RSurf_ActiveModelEntity(ent, false, false, false);
11680
11681         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11682         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11683         VectorNormalize(localnormal);
11684         localsize = worldsize*rsurface.inversematrixscale;
11685         localmins[0] = localorigin[0] - localsize;
11686         localmins[1] = localorigin[1] - localsize;
11687         localmins[2] = localorigin[2] - localsize;
11688         localmaxs[0] = localorigin[0] + localsize;
11689         localmaxs[1] = localorigin[1] + localsize;
11690         localmaxs[2] = localorigin[2] + localsize;
11691
11692         //VectorCopy(localnormal, planes[4]);
11693         //VectorVectors(planes[4], planes[2], planes[0]);
11694         AnglesFromVectors(angles, localnormal, NULL, false);
11695         AngleVectors(angles, planes[0], planes[2], planes[4]);
11696         VectorNegate(planes[0], planes[1]);
11697         VectorNegate(planes[2], planes[3]);
11698         VectorNegate(planes[4], planes[5]);
11699         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11700         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11701         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11702         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11703         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11704         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11705
11706 #if 1
11707 // works
11708 {
11709         matrix4x4_t forwardprojection;
11710         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11711         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11712 }
11713 #else
11714 // broken
11715 {
11716         float projectionvector[4][3];
11717         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11718         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11719         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11720         projectionvector[0][0] = planes[0][0] * ilocalsize;
11721         projectionvector[0][1] = planes[1][0] * ilocalsize;
11722         projectionvector[0][2] = planes[2][0] * ilocalsize;
11723         projectionvector[1][0] = planes[0][1] * ilocalsize;
11724         projectionvector[1][1] = planes[1][1] * ilocalsize;
11725         projectionvector[1][2] = planes[2][1] * ilocalsize;
11726         projectionvector[2][0] = planes[0][2] * ilocalsize;
11727         projectionvector[2][1] = planes[1][2] * ilocalsize;
11728         projectionvector[2][2] = planes[2][2] * ilocalsize;
11729         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11730         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11731         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11732         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11733 }
11734 #endif
11735
11736         dynamic = model->surfmesh.isanimated;
11737         vertex3f = rsurface.modelvertex3f;
11738         numsurfacelist = model->nummodelsurfaces;
11739         surfacelist = model->sortedmodelsurfaces;
11740         surfaces = model->data_surfaces;
11741         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11742         {
11743                 surfaceindex = surfacelist[surfacelistindex];
11744                 surface = surfaces + surfaceindex;
11745                 // check cull box first because it rejects more than any other check
11746                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11747                         continue;
11748                 // skip transparent surfaces
11749                 texture = surface->texture;
11750                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11751                         continue;
11752                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11753                         continue;
11754                 numtriangles = surface->num_triangles;
11755                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
11756                 {
11757                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
11758                         {
11759                                 index = 3*e[cornerindex];
11760                                 VectorCopy(vertex3f + index, v[cornerindex]);
11761                         }
11762                         // cull backfaces
11763                         //TriangleNormal(v[0], v[1], v[2], normal);
11764                         //if (DotProduct(normal, localnormal) < 0.0f)
11765                         //      continue;
11766                         // clip by each of the box planes formed from the projection matrix
11767                         // if anything survives, we emit the decal
11768                         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]);
11769                         if (numpoints < 3)
11770                                 continue;
11771                         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]);
11772                         if (numpoints < 3)
11773                                 continue;
11774                         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]);
11775                         if (numpoints < 3)
11776                                 continue;
11777                         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]);
11778                         if (numpoints < 3)
11779                                 continue;
11780                         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]);
11781                         if (numpoints < 3)
11782                                 continue;
11783                         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]);
11784                         if (numpoints < 3)
11785                                 continue;
11786                         // some part of the triangle survived, so we have to accept it...
11787                         if (dynamic)
11788                         {
11789                                 // dynamic always uses the original triangle
11790                                 numpoints = 3;
11791                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11792                                 {
11793                                         index = 3*e[cornerindex];
11794                                         VectorCopy(vertex3f + index, v[cornerindex]);
11795                                 }
11796                         }
11797                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11798                         {
11799                                 // convert vertex positions to texcoords
11800                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
11801                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11802                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11803                                 // calculate distance fade from the projection origin
11804                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11805                                 f = bound(0.0f, f, 1.0f);
11806                                 c[cornerindex][0] = r * f;
11807                                 c[cornerindex][1] = g * f;
11808                                 c[cornerindex][2] = b * f;
11809                                 c[cornerindex][3] = 1.0f;
11810                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11811                         }
11812                         if (dynamic)
11813                                 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);
11814                         else
11815                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11816                                         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);
11817                 }
11818         }
11819 }
11820
11821 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11822 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)
11823 {
11824         int renderentityindex;
11825         float worldmins[3];
11826         float worldmaxs[3];
11827         entity_render_t *ent;
11828
11829         if (!cl_decals_newsystem.integer)
11830                 return;
11831
11832         worldmins[0] = worldorigin[0] - worldsize;
11833         worldmins[1] = worldorigin[1] - worldsize;
11834         worldmins[2] = worldorigin[2] - worldsize;
11835         worldmaxs[0] = worldorigin[0] + worldsize;
11836         worldmaxs[1] = worldorigin[1] + worldsize;
11837         worldmaxs[2] = worldorigin[2] + worldsize;
11838
11839         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11840
11841         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11842         {
11843                 ent = r_refdef.scene.entities[renderentityindex];
11844                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11845                         continue;
11846
11847                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11848         }
11849 }
11850
11851 typedef struct r_decalsystem_splatqueue_s
11852 {
11853         vec3_t worldorigin;
11854         vec3_t worldnormal;
11855         float color[4];
11856         float tcrange[4];
11857         float worldsize;
11858         int decalsequence;
11859 }
11860 r_decalsystem_splatqueue_t;
11861
11862 int r_decalsystem_numqueued = 0;
11863 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11864
11865 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)
11866 {
11867         r_decalsystem_splatqueue_t *queue;
11868
11869         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11870                 return;
11871
11872         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11873         VectorCopy(worldorigin, queue->worldorigin);
11874         VectorCopy(worldnormal, queue->worldnormal);
11875         Vector4Set(queue->color, r, g, b, a);
11876         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11877         queue->worldsize = worldsize;
11878         queue->decalsequence = cl.decalsequence++;
11879 }
11880
11881 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11882 {
11883         int i;
11884         r_decalsystem_splatqueue_t *queue;
11885
11886         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11887                 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);
11888         r_decalsystem_numqueued = 0;
11889 }
11890
11891 extern cvar_t cl_decals_max;
11892 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11893 {
11894         int i;
11895         decalsystem_t *decalsystem = &ent->decalsystem;
11896         int numdecals;
11897         int killsequence;
11898         tridecal_t *decal;
11899         float frametime;
11900         float lifetime;
11901
11902         if (!decalsystem->numdecals)
11903                 return;
11904
11905         if (r_showsurfaces.integer)
11906                 return;
11907
11908         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11909         {
11910                 R_DecalSystem_Reset(decalsystem);
11911                 return;
11912         }
11913
11914         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11915         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11916
11917         if (decalsystem->lastupdatetime)
11918                 frametime = (cl.time - decalsystem->lastupdatetime);
11919         else
11920                 frametime = 0;
11921         decalsystem->lastupdatetime = cl.time;
11922         decal = decalsystem->decals;
11923         numdecals = decalsystem->numdecals;
11924
11925         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11926         {
11927                 if (decal->color4ub[0][3])
11928                 {
11929                         decal->lived += frametime;
11930                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11931                         {
11932                                 memset(decal, 0, sizeof(*decal));
11933                                 if (decalsystem->freedecal > i)
11934                                         decalsystem->freedecal = i;
11935                         }
11936                 }
11937         }
11938         decal = decalsystem->decals;
11939         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
11940                 numdecals--;
11941
11942         // collapse the array by shuffling the tail decals into the gaps
11943         for (;;)
11944         {
11945                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
11946                         decalsystem->freedecal++;
11947                 if (decalsystem->freedecal == numdecals)
11948                         break;
11949                 decal[decalsystem->freedecal] = decal[--numdecals];
11950         }
11951
11952         decalsystem->numdecals = numdecals;
11953
11954         if (numdecals <= 0)
11955         {
11956                 // if there are no decals left, reset decalsystem
11957                 R_DecalSystem_Reset(decalsystem);
11958         }
11959 }
11960
11961 extern skinframe_t *decalskinframe;
11962 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11963 {
11964         int i;
11965         decalsystem_t *decalsystem = &ent->decalsystem;
11966         int numdecals;
11967         tridecal_t *decal;
11968         float faderate;
11969         float alpha;
11970         float *v3f;
11971         float *c4f;
11972         float *t2f;
11973         const int *e;
11974         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11975         int numtris = 0;
11976
11977         numdecals = decalsystem->numdecals;
11978         if (!numdecals)
11979                 return;
11980
11981         if (r_showsurfaces.integer)
11982                 return;
11983
11984         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11985         {
11986                 R_DecalSystem_Reset(decalsystem);
11987                 return;
11988         }
11989
11990         // if the model is static it doesn't matter what value we give for
11991         // wantnormals and wanttangents, so this logic uses only rules applicable
11992         // to a model, knowing that they are meaningless otherwise
11993         if (ent == r_refdef.scene.worldentity)
11994                 RSurf_ActiveWorldEntity();
11995         else
11996                 RSurf_ActiveModelEntity(ent, false, false, false);
11997
11998         decalsystem->lastupdatetime = cl.time;
11999         decal = decalsystem->decals;
12000
12001         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12002
12003         // update vertex positions for animated models
12004         v3f = decalsystem->vertex3f;
12005         c4f = decalsystem->color4f;
12006         t2f = decalsystem->texcoord2f;
12007         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12008         {
12009                 if (!decal->color4ub[0][3])
12010                         continue;
12011
12012                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12013                         continue;
12014
12015                 // update color values for fading decals
12016                 if (decal->lived >= cl_decals_time.value)
12017                 {
12018                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12019                         alpha *= (1.0f/255.0f);
12020                 }
12021                 else
12022                         alpha = 1.0f/255.0f;
12023
12024                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12025                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12026                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12027                 c4f[ 3] = 1;
12028                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12029                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12030                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12031                 c4f[ 7] = 1;
12032                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12033                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12034                 c4f[10] = decal->color4ub[2][2] * alpha;
12035                 c4f[11] = 1;
12036
12037                 t2f[0] = decal->texcoord2f[0][0];
12038                 t2f[1] = decal->texcoord2f[0][1];
12039                 t2f[2] = decal->texcoord2f[1][0];
12040                 t2f[3] = decal->texcoord2f[1][1];
12041                 t2f[4] = decal->texcoord2f[2][0];
12042                 t2f[5] = decal->texcoord2f[2][1];
12043
12044                 // update vertex positions for animated models
12045                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnum_triangles)
12046                 {
12047                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12048                         VectorCopy(rsurface.vertex3f + 3*e[0], v3f);
12049                         VectorCopy(rsurface.vertex3f + 3*e[1], v3f + 3);
12050                         VectorCopy(rsurface.vertex3f + 3*e[2], v3f + 6);
12051                 }
12052                 else
12053                 {
12054                         VectorCopy(decal->vertex3f[0], v3f);
12055                         VectorCopy(decal->vertex3f[1], v3f + 3);
12056                         VectorCopy(decal->vertex3f[2], v3f + 6);
12057                 }
12058
12059                 v3f += 9;
12060                 c4f += 12;
12061                 t2f += 6;
12062                 numtris++;
12063         }
12064
12065         if (numtris > 0)
12066         {
12067                 r_refdef.stats.drawndecals += numtris;
12068
12069                 if (r_refdef.fogenabled)
12070                 {
12071                         switch(vid.renderpath)
12072                         {
12073                         case RENDERPATH_GL20:
12074                         case RENDERPATH_CGGL:
12075                         case RENDERPATH_GL13:
12076                         case RENDERPATH_GL11:
12077                                 for (i = 0, v3f = decalsystem->vertex3f, c4f = decalsystem->color4f;i < numtris*3;i++, v3f += 3, c4f += 4)
12078                                 {
12079                                         alpha = RSurf_FogVertex(v3f);
12080                                         c4f[0] *= alpha;
12081                                         c4f[1] *= alpha;
12082                                         c4f[2] *= alpha;
12083                                 }
12084                                 break;
12085                         }
12086                 }
12087
12088                 // now render the decals all at once
12089                 // (this assumes they all use one particle font texture!)
12090                 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);
12091                 R_Mesh_ResetTextureState();
12092                 R_Mesh_VertexPointer(decalsystem->vertex3f, 0, 0);
12093                 R_Mesh_TexCoordPointer(0, 2, decalsystem->texcoord2f, 0, 0);
12094                 R_Mesh_ColorPointer(decalsystem->color4f, 0, 0);
12095                 GL_DepthMask(false);
12096                 GL_DepthRange(0, 1);
12097                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12098                 GL_DepthTest(true);
12099                 GL_CullFace(GL_NONE);
12100                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12101                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12102                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, decalsystem->element3s, 0, 0);
12103         }
12104 }
12105
12106 static void R_DrawModelDecals(void)
12107 {
12108         int i, numdecals;
12109
12110         // fade faster when there are too many decals
12111         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12112         for (i = 0;i < r_refdef.scene.numentities;i++)
12113                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12114
12115         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12116         for (i = 0;i < r_refdef.scene.numentities;i++)
12117                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12118                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12119
12120         R_DecalSystem_ApplySplatEntitiesQueue();
12121
12122         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12123         for (i = 0;i < r_refdef.scene.numentities;i++)
12124                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12125
12126         r_refdef.stats.totaldecals += numdecals;
12127
12128         if (r_showsurfaces.integer)
12129                 return;
12130
12131         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12132
12133         for (i = 0;i < r_refdef.scene.numentities;i++)
12134         {
12135                 if (!r_refdef.viewcache.entityvisible[i])
12136                         continue;
12137                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12138                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12139         }
12140 }
12141
12142 void R_DrawDebugModel(void)
12143 {
12144         entity_render_t *ent = rsurface.entity;
12145         int i, j, k, l, flagsmask;
12146         q3mbrush_t *brush;
12147         const msurface_t *surface;
12148         dp_model_t *model = ent->model;
12149         vec3_t v;
12150
12151         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12152
12153         R_Mesh_ColorPointer(NULL, 0, 0);
12154         R_Mesh_ResetTextureState();
12155         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12156         GL_DepthRange(0, 1);
12157         GL_DepthTest(!r_showdisabledepthtest.integer);
12158         GL_DepthMask(false);
12159         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12160
12161         if (r_showcollisionbrushes.value > 0 && model->brush.num_brushes)
12162         {
12163                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12164                 for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
12165                 {
12166                         if (brush->colbrushf && brush->colbrushf->numtriangles)
12167                         {
12168                                 R_Mesh_VertexPointer(brush->colbrushf->points->v, 0, 0);
12169                                 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);
12170                                 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, 0);
12171                         }
12172                 }
12173                 for (i = 0, surface = model->data_surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surface++)
12174                 {
12175                         if (surface->num_collisiontriangles)
12176                         {
12177                                 R_Mesh_VertexPointer(surface->data_collisionvertex3f, 0, 0);
12178                                 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);
12179                                 R_Mesh_Draw(0, surface->num_collisionvertices, 0, surface->num_collisiontriangles, surface->data_collisionelement3i, NULL, 0, 0);
12180                         }
12181                 }
12182         }
12183
12184         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12185
12186         if (r_showtris.integer || r_shownormals.integer)
12187         {
12188                 if (r_showdisabledepthtest.integer)
12189                 {
12190                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12191                         GL_DepthMask(false);
12192                 }
12193                 else
12194                 {
12195                         GL_BlendFunc(GL_ONE, GL_ZERO);
12196                         GL_DepthMask(true);
12197                 }
12198                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12199                 {
12200                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12201                                 continue;
12202                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12203                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12204                         {
12205                                 RSurf_PrepareVerticesForBatch(true, true, 1, &surface);
12206                                 if (r_showtris.value > 0)
12207                                 {
12208                                         if (!rsurface.texture->currentlayers->depthmask)
12209                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12210                                         else if (ent == r_refdef.scene.worldentity)
12211                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12212                                         else
12213                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12214                                         R_Mesh_VertexPointer(rsurface.vertex3f, 0, 0);
12215                                         R_Mesh_ColorPointer(NULL, 0, 0);
12216                                         R_Mesh_TexCoordPointer(0, 0, NULL, 0, 0);
12217                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12218                                         //R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_firsttriangle, surface->num_triangles, model->surfmesh.data_element3i, NULL, 0, 0);
12219                                         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);
12220                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12221                                         CHECKGLERROR
12222                                 }
12223                                 if (r_shownormals.value < 0)
12224                                 {
12225                                         qglBegin(GL_LINES);
12226                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12227                                         {
12228                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12229                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12230                                                 qglVertex3f(v[0], v[1], v[2]);
12231                                                 VectorMA(v, -r_shownormals.value, rsurface.svector3f + l * 3, v);
12232                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12233                                                 qglVertex3f(v[0], v[1], v[2]);
12234                                         }
12235                                         qglEnd();
12236                                         CHECKGLERROR
12237                                 }
12238                                 if (r_shownormals.value > 0)
12239                                 {
12240                                         qglBegin(GL_LINES);
12241                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12242                                         {
12243                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12244                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12245                                                 qglVertex3f(v[0], v[1], v[2]);
12246                                                 VectorMA(v, r_shownormals.value, rsurface.svector3f + l * 3, v);
12247                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12248                                                 qglVertex3f(v[0], v[1], v[2]);
12249                                         }
12250                                         qglEnd();
12251                                         CHECKGLERROR
12252                                         qglBegin(GL_LINES);
12253                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12254                                         {
12255                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12256                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12257                                                 qglVertex3f(v[0], v[1], v[2]);
12258                                                 VectorMA(v, r_shownormals.value, rsurface.tvector3f + l * 3, v);
12259                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12260                                                 qglVertex3f(v[0], v[1], v[2]);
12261                                         }
12262                                         qglEnd();
12263                                         CHECKGLERROR
12264                                         qglBegin(GL_LINES);
12265                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12266                                         {
12267                                                 VectorCopy(rsurface.vertex3f + l * 3, v);
12268                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12269                                                 qglVertex3f(v[0], v[1], v[2]);
12270                                                 VectorMA(v, r_shownormals.value, rsurface.normal3f + l * 3, v);
12271                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12272                                                 qglVertex3f(v[0], v[1], v[2]);
12273                                         }
12274                                         qglEnd();
12275                                         CHECKGLERROR
12276                                 }
12277                         }
12278                 }
12279                 rsurface.texture = NULL;
12280         }
12281 }
12282
12283 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12284 int r_maxsurfacelist = 0;
12285 const msurface_t **r_surfacelist = NULL;
12286 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12287 {
12288         int i, j, endj, flagsmask;
12289         dp_model_t *model = r_refdef.scene.worldmodel;
12290         msurface_t *surfaces;
12291         unsigned char *update;
12292         int numsurfacelist = 0;
12293         if (model == NULL)
12294                 return;
12295
12296         if (r_maxsurfacelist < model->num_surfaces)
12297         {
12298                 r_maxsurfacelist = model->num_surfaces;
12299                 if (r_surfacelist)
12300                         Mem_Free((msurface_t**)r_surfacelist);
12301                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12302         }
12303
12304         RSurf_ActiveWorldEntity();
12305
12306         surfaces = model->data_surfaces;
12307         update = model->brushq1.lightmapupdateflags;
12308
12309         // update light styles on this submodel
12310         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12311         {
12312                 model_brush_lightstyleinfo_t *style;
12313                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12314                 {
12315                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12316                         {
12317                                 int *list = style->surfacelist;
12318                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12319                                 for (j = 0;j < style->numsurfaces;j++)
12320                                         update[list[j]] = true;
12321                         }
12322                 }
12323         }
12324
12325         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12326
12327         if (debug)
12328         {
12329                 R_DrawDebugModel();
12330                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12331                 return;
12332         }
12333
12334         rsurface.uselightmaptexture = false;
12335         rsurface.texture = NULL;
12336         rsurface.rtlight = NULL;
12337         numsurfacelist = 0;
12338         // add visible surfaces to draw list
12339         for (i = 0;i < model->nummodelsurfaces;i++)
12340         {
12341                 j = model->sortedmodelsurfaces[i];
12342                 if (r_refdef.viewcache.world_surfacevisible[j])
12343                         r_surfacelist[numsurfacelist++] = surfaces + j;
12344         }
12345         // update lightmaps if needed
12346         if (model->brushq1.firstrender)
12347         {
12348                 model->brushq1.firstrender = false;
12349                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12350                         if (update[j])
12351                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12352         }
12353         else if (update)
12354         {
12355                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12356                         if (r_refdef.viewcache.world_surfacevisible[j])
12357                                 if (update[j])
12358                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12359         }
12360         // don't do anything if there were no surfaces
12361         if (!numsurfacelist)
12362         {
12363                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12364                 return;
12365         }
12366         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12367         GL_AlphaTest(false);
12368
12369         // add to stats if desired
12370         if (r_speeds.integer && !skysurfaces && !depthonly)
12371         {
12372                 r_refdef.stats.world_surfaces += numsurfacelist;
12373                 for (j = 0;j < numsurfacelist;j++)
12374                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12375         }
12376
12377         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12378 }
12379
12380 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12381 {
12382         int i, j, endj, flagsmask;
12383         dp_model_t *model = ent->model;
12384         msurface_t *surfaces;
12385         unsigned char *update;
12386         int numsurfacelist = 0;
12387         if (model == NULL)
12388                 return;
12389
12390         if (r_maxsurfacelist < model->num_surfaces)
12391         {
12392                 r_maxsurfacelist = model->num_surfaces;
12393                 if (r_surfacelist)
12394                         Mem_Free((msurface_t **)r_surfacelist);
12395                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12396         }
12397
12398         // if the model is static it doesn't matter what value we give for
12399         // wantnormals and wanttangents, so this logic uses only rules applicable
12400         // to a model, knowing that they are meaningless otherwise
12401         if (ent == r_refdef.scene.worldentity)
12402                 RSurf_ActiveWorldEntity();
12403         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12404                 RSurf_ActiveModelEntity(ent, false, false, false);
12405         else if (prepass)
12406                 RSurf_ActiveModelEntity(ent, true, true, true);
12407         else if (depthonly)
12408         {
12409                 switch (vid.renderpath)
12410                 {
12411                 case RENDERPATH_GL20:
12412                 case RENDERPATH_CGGL:
12413                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12414                         break;
12415                 case RENDERPATH_GL13:
12416                 case RENDERPATH_GL11:
12417                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12418                         break;
12419                 }
12420         }
12421         else
12422         {
12423                 switch (vid.renderpath)
12424                 {
12425                 case RENDERPATH_GL20:
12426                 case RENDERPATH_CGGL:
12427                         RSurf_ActiveModelEntity(ent, true, true, false);
12428                         break;
12429                 case RENDERPATH_GL13:
12430                 case RENDERPATH_GL11:
12431                         RSurf_ActiveModelEntity(ent, true, false, false);
12432                         break;
12433                 }
12434         }
12435
12436         surfaces = model->data_surfaces;
12437         update = model->brushq1.lightmapupdateflags;
12438
12439         // update light styles
12440         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12441         {
12442                 model_brush_lightstyleinfo_t *style;
12443                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12444                 {
12445                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12446                         {
12447                                 int *list = style->surfacelist;
12448                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12449                                 for (j = 0;j < style->numsurfaces;j++)
12450                                         update[list[j]] = true;
12451                         }
12452                 }
12453         }
12454
12455         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12456
12457         if (debug)
12458         {
12459                 R_DrawDebugModel();
12460                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12461                 return;
12462         }
12463
12464         rsurface.uselightmaptexture = false;
12465         rsurface.texture = NULL;
12466         rsurface.rtlight = NULL;
12467         numsurfacelist = 0;
12468         // add visible surfaces to draw list
12469         for (i = 0;i < model->nummodelsurfaces;i++)
12470                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12471         // don't do anything if there were no surfaces
12472         if (!numsurfacelist)
12473         {
12474                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12475                 return;
12476         }
12477         // update lightmaps if needed
12478         if (update)
12479         {
12480                 int updated = 0;
12481                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12482                 {
12483                         if (update[j])
12484                         {
12485                                 updated++;
12486                                 R_BuildLightMap(ent, surfaces + j);
12487                         }
12488                 }
12489         }
12490         if (update)
12491                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12492                         if (update[j])
12493                                 R_BuildLightMap(ent, surfaces + j);
12494         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12495         GL_AlphaTest(false);
12496
12497         // add to stats if desired
12498         if (r_speeds.integer && !skysurfaces && !depthonly)
12499         {
12500                 r_refdef.stats.entities_surfaces += numsurfacelist;
12501                 for (j = 0;j < numsurfacelist;j++)
12502                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12503         }
12504
12505         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12506 }
12507
12508 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12509 {
12510         static texture_t texture;
12511         static msurface_t surface;
12512         const msurface_t *surfacelist = &surface;
12513
12514         // fake enough texture and surface state to render this geometry
12515
12516         texture.update_lastrenderframe = -1; // regenerate this texture
12517         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12518         texture.currentskinframe = skinframe;
12519         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12520         texture.specularscalemod = 1;
12521         texture.specularpowermod = 1;
12522
12523         surface.texture = &texture;
12524         surface.num_triangles = numtriangles;
12525         surface.num_firsttriangle = firsttriangle;
12526         surface.num_vertices = numvertices;
12527         surface.num_firstvertex = firstvertex;
12528
12529         // now render it
12530         rsurface.texture = R_GetCurrentTexture(surface.texture);
12531         rsurface.uselightmaptexture = false;
12532         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12533 }
12534
12535 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)
12536 {
12537         static msurface_t surface;
12538         const msurface_t *surfacelist = &surface;
12539
12540         // fake enough texture and surface state to render this geometry
12541
12542         surface.texture = texture;
12543         surface.num_triangles = numtriangles;
12544         surface.num_firsttriangle = firsttriangle;
12545         surface.num_vertices = numvertices;
12546         surface.num_firstvertex = firstvertex;
12547
12548         // now render it
12549         rsurface.texture = R_GetCurrentTexture(surface.texture);
12550         rsurface.uselightmaptexture = false;
12551         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12552 }