]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
overhauled vertex formats, now supports 100% interleaved arrays
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 mempool_t *r_main_mempool;
32 rtexturepool_t *r_main_texturepool;
33
34 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
35
36 static qboolean r_loadnormalmap;
37 static qboolean r_loadgloss;
38 qboolean r_loadfog;
39 static qboolean r_loaddds;
40 static qboolean r_savedds;
41
42 //
43 // screen size info
44 //
45 r_refdef_t r_refdef;
46
47 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
48 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
49 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
50 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
51 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)"};
52 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
53 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
54 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
55
56 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
57 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"};
58 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
59 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)"};
60 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
61
62 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"};
63 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
64 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
65 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
66 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
67 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
68 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)"};
69 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
70 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
71 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"};
72 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"};
73 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
74 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"};
75 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"};
76 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"};
77 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
78 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
79 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
80 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
81 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
82 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)"};
83 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)"};
84 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
85 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
86 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
87 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
88 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
89 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
90 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
91 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."};
92 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
93 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
94 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
95 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."};
96 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
97 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
98 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
99 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
100 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"};
101 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"};
102 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
103 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
104 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
105 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
106 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"};
107
108 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
109 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
110 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
111 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
112 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
113 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
114 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
115 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
116
117 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)"};
118 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"};
119
120 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
121 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
122 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
124 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
125
126 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
127 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
128 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
129
130 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)"};
131 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
132 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
133 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
134 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
135 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)"};
136 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)"};
137 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)"};
138 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)"};
139
140 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)"};
141 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
142 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"};
143 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
144 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
145
146 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
147 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
148 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
149 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
150
151 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
152 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
153 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
154 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
155 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
156 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
157 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
158
159 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
160 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
161 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
162 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)"};
163
164 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"};
165
166 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"};
167
168 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
169
170 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
171 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"};
172 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
173 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
174 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
175 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
176 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)"};
177
178 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
179
180 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)"};
181
182 extern cvar_t v_glslgamma;
183
184 extern qboolean v_flipped_state;
185
186 static struct r_bloomstate_s
187 {
188         qboolean enabled;
189         qboolean hdr;
190
191         int bloomwidth, bloomheight;
192
193         int screentexturewidth, screentextureheight;
194         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
195
196         int bloomtexturewidth, bloomtextureheight;
197         rtexture_t *texture_bloom;
198
199         // arrays for rendering the screen passes
200         float screentexcoord2f[8];
201         float bloomtexcoord2f[8];
202         float offsettexcoord2f[8];
203
204         r_viewport_t viewport;
205 }
206 r_bloomstate;
207
208 r_waterstate_t r_waterstate;
209
210 /// shadow volume bsp struct with automatically growing nodes buffer
211 svbsp_t r_svbsp;
212
213 rtexture_t *r_texture_blanknormalmap;
214 rtexture_t *r_texture_white;
215 rtexture_t *r_texture_grey128;
216 rtexture_t *r_texture_black;
217 rtexture_t *r_texture_notexture;
218 rtexture_t *r_texture_whitecube;
219 rtexture_t *r_texture_normalizationcube;
220 rtexture_t *r_texture_fogattenuation;
221 rtexture_t *r_texture_fogheighttexture;
222 rtexture_t *r_texture_gammaramps;
223 unsigned int r_texture_gammaramps_serial;
224 //rtexture_t *r_texture_fogintensity;
225 rtexture_t *r_texture_reflectcube;
226
227 // TODO: hash lookups?
228 typedef struct cubemapinfo_s
229 {
230         char basename[64];
231         rtexture_t *texture;
232 }
233 cubemapinfo_t;
234
235 int r_texture_numcubemaps;
236 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
237
238 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
239 unsigned int r_numqueries;
240 unsigned int r_maxqueries;
241
242 typedef struct r_qwskincache_s
243 {
244         char name[MAX_QPATH];
245         skinframe_t *skinframe;
246 }
247 r_qwskincache_t;
248
249 static r_qwskincache_t *r_qwskincache;
250 static int r_qwskincache_size;
251
252 /// vertex coordinates for a quad that covers the screen exactly
253 const float r_screenvertex3f[12] =
254 {
255         0, 0, 0,
256         1, 0, 0,
257         1, 1, 0,
258         0, 1, 0
259 };
260
261 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
262 {
263         int i;
264         for (i = 0;i < verts;i++)
265         {
266                 out[0] = in[0] * r;
267                 out[1] = in[1] * g;
268                 out[2] = in[2] * b;
269                 out[3] = in[3];
270                 in += 4;
271                 out += 4;
272         }
273 }
274
275 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
276 {
277         int i;
278         for (i = 0;i < verts;i++)
279         {
280                 out[0] = r;
281                 out[1] = g;
282                 out[2] = b;
283                 out[3] = a;
284                 out += 4;
285         }
286 }
287
288 // FIXME: move this to client?
289 void FOG_clear(void)
290 {
291         if (gamemode == GAME_NEHAHRA)
292         {
293                 Cvar_Set("gl_fogenable", "0");
294                 Cvar_Set("gl_fogdensity", "0.2");
295                 Cvar_Set("gl_fogred", "0.3");
296                 Cvar_Set("gl_foggreen", "0.3");
297                 Cvar_Set("gl_fogblue", "0.3");
298         }
299         r_refdef.fog_density = 0;
300         r_refdef.fog_red = 0;
301         r_refdef.fog_green = 0;
302         r_refdef.fog_blue = 0;
303         r_refdef.fog_alpha = 1;
304         r_refdef.fog_start = 0;
305         r_refdef.fog_end = 16384;
306         r_refdef.fog_height = 1<<30;
307         r_refdef.fog_fadedepth = 128;
308         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
309 }
310
311 static void R_BuildBlankTextures(void)
312 {
313         unsigned char data[4];
314         data[2] = 128; // normal X
315         data[1] = 128; // normal Y
316         data[0] = 255; // normal Z
317         data[3] = 128; // height
318         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
319         data[0] = 255;
320         data[1] = 255;
321         data[2] = 255;
322         data[3] = 255;
323         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
324         data[0] = 128;
325         data[1] = 128;
326         data[2] = 128;
327         data[3] = 255;
328         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
329         data[0] = 0;
330         data[1] = 0;
331         data[2] = 0;
332         data[3] = 255;
333         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, NULL);
334 }
335
336 static void R_BuildNoTexture(void)
337 {
338         int x, y;
339         unsigned char pix[16][16][4];
340         // this makes a light grey/dark grey checkerboard texture
341         for (y = 0;y < 16;y++)
342         {
343                 for (x = 0;x < 16;x++)
344                 {
345                         if ((y < 8) ^ (x < 8))
346                         {
347                                 pix[y][x][0] = 128;
348                                 pix[y][x][1] = 128;
349                                 pix[y][x][2] = 128;
350                                 pix[y][x][3] = 255;
351                         }
352                         else
353                         {
354                                 pix[y][x][0] = 64;
355                                 pix[y][x][1] = 64;
356                                 pix[y][x][2] = 64;
357                                 pix[y][x][3] = 255;
358                         }
359                 }
360         }
361         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, NULL);
362 }
363
364 static void R_BuildWhiteCube(void)
365 {
366         unsigned char data[6*1*1*4];
367         memset(data, 255, sizeof(data));
368         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
369 }
370
371 static void R_BuildNormalizationCube(void)
372 {
373         int x, y, side;
374         vec3_t v;
375         vec_t s, t, intensity;
376 #define NORMSIZE 64
377         unsigned char *data;
378         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
379         for (side = 0;side < 6;side++)
380         {
381                 for (y = 0;y < NORMSIZE;y++)
382                 {
383                         for (x = 0;x < NORMSIZE;x++)
384                         {
385                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
386                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
387                                 switch(side)
388                                 {
389                                 default:
390                                 case 0:
391                                         v[0] = 1;
392                                         v[1] = -t;
393                                         v[2] = -s;
394                                         break;
395                                 case 1:
396                                         v[0] = -1;
397                                         v[1] = -t;
398                                         v[2] = s;
399                                         break;
400                                 case 2:
401                                         v[0] = s;
402                                         v[1] = 1;
403                                         v[2] = t;
404                                         break;
405                                 case 3:
406                                         v[0] = s;
407                                         v[1] = -1;
408                                         v[2] = -t;
409                                         break;
410                                 case 4:
411                                         v[0] = s;
412                                         v[1] = -t;
413                                         v[2] = 1;
414                                         break;
415                                 case 5:
416                                         v[0] = -s;
417                                         v[1] = -t;
418                                         v[2] = -1;
419                                         break;
420                                 }
421                                 intensity = 127.0f / sqrt(DotProduct(v, v));
422                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
423                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
424                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
425                                 data[((side*64+y)*64+x)*4+3] = 255;
426                         }
427                 }
428         }
429         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, NULL);
430         Mem_Free(data);
431 }
432
433 static void R_BuildFogTexture(void)
434 {
435         int x, b;
436 #define FOGWIDTH 256
437         unsigned char data1[FOGWIDTH][4];
438         //unsigned char data2[FOGWIDTH][4];
439         double d, r, alpha;
440
441         r_refdef.fogmasktable_start = r_refdef.fog_start;
442         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
443         r_refdef.fogmasktable_range = r_refdef.fogrange;
444         r_refdef.fogmasktable_density = r_refdef.fog_density;
445
446         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
447         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
448         {
449                 d = (x * r - r_refdef.fogmasktable_start);
450                 if(developer_extra.integer)
451                         Con_DPrintf("%f ", d);
452                 d = max(0, d);
453                 if (r_fog_exp2.integer)
454                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
455                 else
456                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
457                 if(developer_extra.integer)
458                         Con_DPrintf(" : %f ", alpha);
459                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
460                 if(developer_extra.integer)
461                         Con_DPrintf(" = %f\n", alpha);
462                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
463         }
464
465         for (x = 0;x < FOGWIDTH;x++)
466         {
467                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
468                 data1[x][0] = b;
469                 data1[x][1] = b;
470                 data1[x][2] = b;
471                 data1[x][3] = 255;
472                 //data2[x][0] = 255 - b;
473                 //data2[x][1] = 255 - b;
474                 //data2[x][2] = 255 - b;
475                 //data2[x][3] = 255;
476         }
477         if (r_texture_fogattenuation)
478         {
479                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
480                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
481         }
482         else
483         {
484                 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);
485                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
486         }
487 }
488
489 static void R_BuildFogHeightTexture(void)
490 {
491         unsigned char *inpixels;
492         int size;
493         int x;
494         int y;
495         int j;
496         float c[4];
497         float f;
498         inpixels = NULL;
499         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
500         if (r_refdef.fogheighttexturename[0])
501                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false);
502         if (!inpixels)
503         {
504                 r_refdef.fog_height_tablesize = 0;
505                 if (r_texture_fogheighttexture)
506                         R_FreeTexture(r_texture_fogheighttexture);
507                 r_texture_fogheighttexture = NULL;
508                 if (r_refdef.fog_height_table2d)
509                         Mem_Free(r_refdef.fog_height_table2d);
510                 r_refdef.fog_height_table2d = NULL;
511                 if (r_refdef.fog_height_table1d)
512                         Mem_Free(r_refdef.fog_height_table1d);
513                 r_refdef.fog_height_table1d = NULL;
514                 return;
515         }
516         size = image_width;
517         r_refdef.fog_height_tablesize = size;
518         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
519         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
520         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
521         Mem_Free(inpixels);
522         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
523         // average fog color table accounting for every fog layer between a point
524         // and the camera.  (Note: attenuation is handled separately!)
525         for (y = 0;y < size;y++)
526         {
527                 for (x = 0;x < size;x++)
528                 {
529                         Vector4Clear(c);
530                         f = 0;
531                         if (x < y)
532                         {
533                                 for (j = x;j <= y;j++)
534                                 {
535                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
536                                         f++;
537                                 }
538                         }
539                         else
540                         {
541                                 for (j = x;j >= y;j--)
542                                 {
543                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
544                                         f++;
545                                 }
546                         }
547                         f = 1.0f / f;
548                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
549                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
550                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
552                 }
553         }
554         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, NULL);
555 }
556
557 //=======================================================================================================================================================
558
559 static const char *builtinshaderstring =
560 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
561 "// written by Forest 'LordHavoc' Hale\n"
562 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
563 "\n"
564 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
565 "# define USEFOG\n"
566 "#endif\n"
567 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
568 "#define USELIGHTMAP\n"
569 "#endif\n"
570 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
571 "#define USEEYEVECTOR\n"
572 "#endif\n"
573 "\n"
574 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
575 "# extension GL_ARB_texture_rectangle : enable\n"
576 "#endif\n"
577 "\n"
578 "#ifdef USESHADOWMAP2D\n"
579 "# ifdef GL_EXT_gpu_shader4\n"
580 "#   extension GL_EXT_gpu_shader4 : enable\n"
581 "# endif\n"
582 "# ifdef GL_ARB_texture_gather\n"
583 "#   extension GL_ARB_texture_gather : enable\n"
584 "# else\n"
585 "#   ifdef GL_AMD_texture_texture4\n"
586 "#     extension GL_AMD_texture_texture4 : enable\n"
587 "#   endif\n"
588 "# endif\n"
589 "#endif\n"
590 "\n"
591 "#ifdef USESHADOWMAPCUBE\n"
592 "# extension GL_EXT_gpu_shader4 : enable\n"
593 "#endif\n"
594 "\n"
595 "//#ifdef USESHADOWSAMPLER\n"
596 "//# extension GL_ARB_shadow : enable\n"
597 "//#endif\n"
598 "\n"
599 "//#ifdef __GLSL_CG_DATA_TYPES\n"
600 "//# define myhalf half\n"
601 "//# define myhalf2 half2\n"
602 "//# define myhalf3 half3\n"
603 "//# define myhalf4 half4\n"
604 "//#else\n"
605 "# define myhalf float\n"
606 "# define myhalf2 vec2\n"
607 "# define myhalf3 vec3\n"
608 "# define myhalf4 vec4\n"
609 "//#endif\n"
610 "\n"
611 "#ifdef VERTEX_SHADER\n"
612 "uniform mat4 ModelViewProjectionMatrix;\n"
613 "#endif\n"
614 "\n"
615 "#ifdef MODE_DEPTH_OR_SHADOW\n"
616 "#ifdef VERTEX_SHADER\n"
617 "void main(void)\n"
618 "{\n"
619 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
620 "}\n"
621 "#endif\n"
622 "#else // !MODE_DEPTH_ORSHADOW\n"
623 "\n"
624 "\n"
625 "\n"
626 "\n"
627 "#ifdef MODE_SHOWDEPTH\n"
628 "#ifdef VERTEX_SHADER\n"
629 "void main(void)\n"
630 "{\n"
631 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
632 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
633 "}\n"
634 "#endif\n"
635 "\n"
636 "#ifdef FRAGMENT_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_FragColor = gl_Color;\n"
640 "}\n"
641 "#endif\n"
642 "#else // !MODE_SHOWDEPTH\n"
643 "\n"
644 "\n"
645 "\n"
646 "\n"
647 "#ifdef MODE_POSTPROCESS\n"
648 "varying vec2 TexCoord1;\n"
649 "varying vec2 TexCoord2;\n"
650 "\n"
651 "#ifdef VERTEX_SHADER\n"
652 "void main(void)\n"
653 "{\n"
654 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
655 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
656 "#ifdef USEBLOOM\n"
657 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
658 "#endif\n"
659 "}\n"
660 "#endif\n"
661 "\n"
662 "#ifdef FRAGMENT_SHADER\n"
663 "uniform sampler2D Texture_First;\n"
664 "#ifdef USEBLOOM\n"
665 "uniform sampler2D Texture_Second;\n"
666 "#endif\n"
667 "#ifdef USEGAMMARAMPS\n"
668 "uniform sampler2D Texture_GammaRamps;\n"
669 "#endif\n"
670 "#ifdef USESATURATION\n"
671 "uniform float Saturation;\n"
672 "#endif\n"
673 "#ifdef USEVIEWTINT\n"
674 "uniform vec4 ViewTintColor;\n"
675 "#endif\n"
676 "//uncomment these if you want to use them:\n"
677 "uniform vec4 UserVec1;\n"
678 "// uniform vec4 UserVec2;\n"
679 "// uniform vec4 UserVec3;\n"
680 "// uniform vec4 UserVec4;\n"
681 "// uniform float ClientTime;\n"
682 "uniform vec2 PixelSize;\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
686 "#ifdef USEBLOOM\n"
687 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
688 "#endif\n"
689 "#ifdef USEVIEWTINT\n"
690 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
691 "#endif\n"
692 "\n"
693 "#ifdef USEPOSTPROCESSING\n"
694 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
695 "// 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"
696 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
697 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
698 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
699 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
700 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
701 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
702 "#endif\n"
703 "\n"
704 "#ifdef USESATURATION\n"
705 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
706 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
707 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
708 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
709 "#endif\n"
710 "\n"
711 "#ifdef USEGAMMARAMPS\n"
712 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
713 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
714 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
715 "#endif\n"
716 "}\n"
717 "#endif\n"
718 "#else // !MODE_POSTPROCESS\n"
719 "\n"
720 "\n"
721 "\n"
722 "\n"
723 "#ifdef MODE_GENERIC\n"
724 "#ifdef USEDIFFUSE\n"
725 "varying vec2 TexCoord1;\n"
726 "#endif\n"
727 "#ifdef USESPECULAR\n"
728 "varying vec2 TexCoord2;\n"
729 "#endif\n"
730 "#ifdef VERTEX_SHADER\n"
731 "void main(void)\n"
732 "{\n"
733 "       gl_FrontColor = gl_Color;\n"
734 "#ifdef USEDIFFUSE\n"
735 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
736 "#endif\n"
737 "#ifdef USESPECULAR\n"
738 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
739 "#endif\n"
740 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
741 "}\n"
742 "#endif\n"
743 "\n"
744 "#ifdef FRAGMENT_SHADER\n"
745 "#ifdef USEDIFFUSE\n"
746 "uniform sampler2D Texture_First;\n"
747 "#endif\n"
748 "#ifdef USESPECULAR\n"
749 "uniform sampler2D Texture_Second;\n"
750 "#endif\n"
751 "\n"
752 "void main(void)\n"
753 "{\n"
754 "       gl_FragColor = gl_Color;\n"
755 "#ifdef USEDIFFUSE\n"
756 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
757 "#endif\n"
758 "\n"
759 "#ifdef USESPECULAR\n"
760 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
761 "# ifdef USECOLORMAPPING\n"
762 "       gl_FragColor *= tex2;\n"
763 "# endif\n"
764 "# ifdef USEGLOW\n"
765 "       gl_FragColor += tex2;\n"
766 "# endif\n"
767 "# ifdef USEVERTEXTEXTUREBLEND\n"
768 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
769 "# endif\n"
770 "#endif\n"
771 "}\n"
772 "#endif\n"
773 "#else // !MODE_GENERIC\n"
774 "\n"
775 "\n"
776 "\n"
777 "\n"
778 "#ifdef MODE_BLOOMBLUR\n"
779 "varying TexCoord;\n"
780 "#ifdef VERTEX_SHADER\n"
781 "void main(void)\n"
782 "{\n"
783 "       gl_FrontColor = gl_Color;\n"
784 "       TexCoord = gl_MultiTexCoord0.xy;\n"
785 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
786 "}\n"
787 "#endif\n"
788 "\n"
789 "#ifdef FRAGMENT_SHADER\n"
790 "uniform sampler2D Texture_First;\n"
791 "uniform vec4 BloomBlur_Parameters;\n"
792 "\n"
793 "void main(void)\n"
794 "{\n"
795 "       int i;\n"
796 "       vec2 tc = TexCoord;\n"
797 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
798 "       tc += BloomBlur_Parameters.xy;\n"
799 "       for (i = 1;i < SAMPLES;i++)\n"
800 "       {\n"
801 "               color += texture2D(Texture_First, tc).rgb;\n"
802 "               tc += BloomBlur_Parameters.xy;\n"
803 "       }\n"
804 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
805 "}\n"
806 "#endif\n"
807 "#else // !MODE_BLOOMBLUR\n"
808 "#ifdef MODE_REFRACTION\n"
809 "varying vec2 TexCoord;\n"
810 "varying vec4 ModelViewProjectionPosition;\n"
811 "uniform mat4 TexMatrix;\n"
812 "#ifdef VERTEX_SHADER\n"
813 "\n"
814 "void main(void)\n"
815 "{\n"
816 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
817 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
818 "       ModelViewProjectionPosition = gl_Position;\n"
819 "}\n"
820 "#endif\n"
821 "\n"
822 "#ifdef FRAGMENT_SHADER\n"
823 "uniform sampler2D Texture_Normal;\n"
824 "uniform sampler2D Texture_Refraction;\n"
825 "uniform sampler2D Texture_Reflection;\n"
826 "\n"
827 "uniform vec4 DistortScaleRefractReflect;\n"
828 "uniform vec4 ScreenScaleRefractReflect;\n"
829 "uniform vec4 ScreenCenterRefractReflect;\n"
830 "uniform vec4 RefractColor;\n"
831 "uniform vec4 ReflectColor;\n"
832 "uniform float ReflectFactor;\n"
833 "uniform float ReflectOffset;\n"
834 "\n"
835 "void main(void)\n"
836 "{\n"
837 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
838 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
839 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
840 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
841 "       // FIXME temporary hack to detect the case that the reflection\n"
842 "       // gets blackened at edges due to leaving the area that contains actual\n"
843 "       // content.\n"
844 "       // Remove this 'ack once we have a better way to stop this thing from\n"
845 "       // 'appening.\n"
846 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
847 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
848 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
849 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
850 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
851 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_REFRACTION\n"
855 "\n"
856 "\n"
857 "\n"
858 "\n"
859 "#ifdef MODE_WATER\n"
860 "varying vec2 TexCoord;\n"
861 "varying vec3 EyeVector;\n"
862 "varying vec4 ModelViewProjectionPosition;\n"
863 "#ifdef VERTEX_SHADER\n"
864 "uniform vec3 EyePosition;\n"
865 "uniform mat4 TexMatrix;\n"
866 "\n"
867 "void main(void)\n"
868 "{\n"
869 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
870 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
871 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
872 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
873 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
874 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
875 "       ModelViewProjectionPosition = gl_Position;\n"
876 "}\n"
877 "#endif\n"
878 "\n"
879 "#ifdef FRAGMENT_SHADER\n"
880 "uniform sampler2D Texture_Normal;\n"
881 "uniform sampler2D Texture_Refraction;\n"
882 "uniform sampler2D Texture_Reflection;\n"
883 "\n"
884 "uniform vec4 DistortScaleRefractReflect;\n"
885 "uniform vec4 ScreenScaleRefractReflect;\n"
886 "uniform vec4 ScreenCenterRefractReflect;\n"
887 "uniform vec4 RefractColor;\n"
888 "uniform vec4 ReflectColor;\n"
889 "uniform float ReflectFactor;\n"
890 "uniform float ReflectOffset;\n"
891 "\n"
892 "void main(void)\n"
893 "{\n"
894 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
895 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
896 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
897 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
898 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
899 "       // FIXME temporary hack to detect the case that the reflection\n"
900 "       // gets blackened at edges due to leaving the area that contains actual\n"
901 "       // content.\n"
902 "       // Remove this 'ack once we have a better way to stop this thing from\n"
903 "       // 'appening.\n"
904 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
905 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
906 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
907 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
908 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
909 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
910 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
911 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
913 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
914 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
915 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
916 "}\n"
917 "#endif\n"
918 "#else // !MODE_WATER\n"
919 "\n"
920 "\n"
921 "\n"
922 "\n"
923 "// common definitions between vertex shader and fragment shader:\n"
924 "\n"
925 "varying vec2 TexCoord;\n"
926 "#ifdef USEVERTEXTEXTUREBLEND\n"
927 "varying vec2 TexCoord2;\n"
928 "#endif\n"
929 "#ifdef USELIGHTMAP\n"
930 "varying vec2 TexCoordLightmap;\n"
931 "#endif\n"
932 "\n"
933 "#ifdef MODE_LIGHTSOURCE\n"
934 "varying vec3 CubeVector;\n"
935 "#endif\n"
936 "\n"
937 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
938 "varying vec3 LightVector;\n"
939 "#endif\n"
940 "\n"
941 "#ifdef USEEYEVECTOR\n"
942 "varying vec3 EyeVector;\n"
943 "#endif\n"
944 "#ifdef USEFOG\n"
945 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
946 "#endif\n"
947 "\n"
948 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
949 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
950 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
951 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
952 "#endif\n"
953 "\n"
954 "#ifdef USEREFLECTION\n"
955 "varying vec4 ModelViewProjectionPosition;\n"
956 "#endif\n"
957 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
958 "uniform vec3 LightPosition;\n"
959 "varying vec4 ModelViewPosition;\n"
960 "#endif\n"
961 "\n"
962 "#ifdef MODE_LIGHTSOURCE\n"
963 "uniform vec3 LightPosition;\n"
964 "#endif\n"
965 "uniform vec3 EyePosition;\n"
966 "#ifdef MODE_LIGHTDIRECTION\n"
967 "uniform vec3 LightDir;\n"
968 "#endif\n"
969 "uniform vec4 FogPlane;\n"
970 "\n"
971 "#ifdef USESHADOWMAPORTHO\n"
972 "varying vec3 ShadowMapTC;\n"
973 "#endif\n"
974 "\n"
975 "\n"
976 "\n"
977 "\n"
978 "\n"
979 "// 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"
980 "\n"
981 "// fragment shader specific:\n"
982 "#ifdef FRAGMENT_SHADER\n"
983 "\n"
984 "uniform sampler2D Texture_Normal;\n"
985 "uniform sampler2D Texture_Color;\n"
986 "uniform sampler2D Texture_Gloss;\n"
987 "#ifdef USEGLOW\n"
988 "uniform sampler2D Texture_Glow;\n"
989 "#endif\n"
990 "#ifdef USEVERTEXTEXTUREBLEND\n"
991 "uniform sampler2D Texture_SecondaryNormal;\n"
992 "uniform sampler2D Texture_SecondaryColor;\n"
993 "uniform sampler2D Texture_SecondaryGloss;\n"
994 "#ifdef USEGLOW\n"
995 "uniform sampler2D Texture_SecondaryGlow;\n"
996 "#endif\n"
997 "#endif\n"
998 "#ifdef USECOLORMAPPING\n"
999 "uniform sampler2D Texture_Pants;\n"
1000 "uniform sampler2D Texture_Shirt;\n"
1001 "#endif\n"
1002 "#ifdef USEFOG\n"
1003 "#ifdef USEFOGHEIGHTTEXTURE\n"
1004 "uniform sampler2D Texture_FogHeightTexture;\n"
1005 "#endif\n"
1006 "uniform sampler2D Texture_FogMask;\n"
1007 "#endif\n"
1008 "#ifdef USELIGHTMAP\n"
1009 "uniform sampler2D Texture_Lightmap;\n"
1010 "#endif\n"
1011 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1012 "uniform sampler2D Texture_Deluxemap;\n"
1013 "#endif\n"
1014 "#ifdef USEREFLECTION\n"
1015 "uniform sampler2D Texture_Reflection;\n"
1016 "#endif\n"
1017 "\n"
1018 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1019 "uniform sampler2D Texture_ScreenDepth;\n"
1020 "uniform sampler2D Texture_ScreenNormalMap;\n"
1021 "#endif\n"
1022 "#ifdef USEDEFERREDLIGHTMAP\n"
1023 "uniform sampler2D Texture_ScreenDiffuse;\n"
1024 "uniform sampler2D Texture_ScreenSpecular;\n"
1025 "#endif\n"
1026 "\n"
1027 "uniform myhalf3 Color_Pants;\n"
1028 "uniform myhalf3 Color_Shirt;\n"
1029 "uniform myhalf3 FogColor;\n"
1030 "\n"
1031 "#ifdef USEFOG\n"
1032 "uniform float FogRangeRecip;\n"
1033 "uniform float FogPlaneViewDist;\n"
1034 "uniform float FogHeightFade;\n"
1035 "vec3 FogVertex(vec3 surfacecolor)\n"
1036 "{\n"
1037 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1038 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1039 "       float fogfrac;\n"
1040 "#ifdef USEFOGHEIGHTTEXTURE\n"
1041 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1042 "       fogfrac = fogheightpixel.a;\n"
1043 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1044 "#else\n"
1045 "# ifdef USEFOGOUTSIDE\n"
1046 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1047 "# else\n"
1048 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1049 "# endif\n"
1050 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1051 "#endif\n"
1052 "}\n"
1053 "#endif\n"
1054 "\n"
1055 "#ifdef USEOFFSETMAPPING\n"
1056 "uniform float OffsetMapping_Scale;\n"
1057 "vec2 OffsetMapping(vec2 TexCoord)\n"
1058 "{\n"
1059 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1060 "       // 14 sample relief mapping: linear search and then binary search\n"
1061 "       // this basically steps forward a small amount repeatedly until it finds\n"
1062 "       // itself inside solid, then jitters forward and back using decreasing\n"
1063 "       // amounts to find the impact\n"
1064 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1065 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1066 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1067 "       vec3 RT = vec3(TexCoord, 1);\n"
1068 "       OffsetVector *= 0.1;\n"
1069 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1070 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1071 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1072 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1073 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1074 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1075 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1076 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1077 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1078 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1079 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1080 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1081 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1082 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1083 "       return RT.xy;\n"
1084 "#else\n"
1085 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1086 "       // this basically moves forward the full distance, and then backs up based\n"
1087 "       // on height of samples\n"
1088 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1089 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1090 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1091 "       TexCoord += OffsetVector;\n"
1092 "       OffsetVector *= 0.333;\n"
1093 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1094 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1095 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1096 "       return TexCoord;\n"
1097 "#endif\n"
1098 "}\n"
1099 "#endif // USEOFFSETMAPPING\n"
1100 "\n"
1101 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1102 "uniform sampler2D Texture_Attenuation;\n"
1103 "uniform samplerCube Texture_Cube;\n"
1104 "#endif\n"
1105 "\n"
1106 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1107 "\n"
1108 "#ifdef USESHADOWMAPRECT\n"
1109 "# ifdef USESHADOWSAMPLER\n"
1110 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1111 "# else\n"
1112 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1113 "# endif\n"
1114 "#endif\n"
1115 "\n"
1116 "#ifdef USESHADOWMAP2D\n"
1117 "# ifdef USESHADOWSAMPLER\n"
1118 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1119 "# else\n"
1120 "uniform sampler2D Texture_ShadowMap2D;\n"
1121 "# endif\n"
1122 "#endif\n"
1123 "\n"
1124 "#ifdef USESHADOWMAPVSDCT\n"
1125 "uniform samplerCube Texture_CubeProjection;\n"
1126 "#endif\n"
1127 "\n"
1128 "#ifdef USESHADOWMAPCUBE\n"
1129 "# ifdef USESHADOWSAMPLER\n"
1130 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1131 "# else\n"
1132 "uniform samplerCube Texture_ShadowMapCube;\n"
1133 "# endif\n"
1134 "#endif\n"
1135 "\n"
1136 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1137 "uniform vec2 ShadowMap_TextureScale;\n"
1138 "uniform vec4 ShadowMap_Parameters;\n"
1139 "#endif\n"
1140 "\n"
1141 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1142 "# ifdef USESHADOWMAPORTHO\n"
1143 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1144 "# else\n"
1145 "#  ifdef USESHADOWMAPVSDCT\n"
1146 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1147 "{\n"
1148 "       vec3 adir = abs(dir);\n"
1149 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1150 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1151 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1152 "}\n"
1153 "#  else\n"
1154 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1155 "{\n"
1156 "       vec3 adir = abs(dir);\n"
1157 "       float ma = adir.z;\n"
1158 "       vec4 proj = vec4(dir, 2.5);\n"
1159 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1160 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1161 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1162 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1163 "}\n"
1164 "#  endif\n"
1165 "# endif\n"
1166 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1167 "\n"
1168 "#ifdef USESHADOWMAPCUBE\n"
1169 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1173 "}\n"
1174 "#endif\n"
1175 "\n"
1176 "# ifdef USESHADOWMAPRECT\n"
1177 "float ShadowMapCompare(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1180 "       float f;\n"
1181 "#  ifdef USESHADOWSAMPLER\n"
1182 "\n"
1183 "#    ifdef USESHADOWMAPPCF\n"
1184 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1185 "       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"
1186 "#    else\n"
1187 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1188 "#    endif\n"
1189 "\n"
1190 "#  else\n"
1191 "\n"
1192 "#    ifdef USESHADOWMAPPCF\n"
1193 "#      if USESHADOWMAPPCF > 1\n"
1194 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1195 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1196 "       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"
1197 "       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"
1198 "       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"
1199 "       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"
1200 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1201 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1202 "#      else\n"
1203 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1204 "       vec2 offset = fract(shadowmaptc.xy);\n"
1205 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1206 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1207 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1208 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1209 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1210 "#      endif\n"
1211 "#    else\n"
1212 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1213 "#    endif\n"
1214 "\n"
1215 "#  endif\n"
1216 "#  ifdef USESHADOWMAPORTHO\n"
1217 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1218 "#  else\n"
1219 "       return f;\n"
1220 "#  endif\n"
1221 "}\n"
1222 "# endif\n"
1223 "\n"
1224 "# ifdef USESHADOWMAP2D\n"
1225 "float ShadowMapCompare(vec3 dir)\n"
1226 "{\n"
1227 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1228 "       float f;\n"
1229 "\n"
1230 "#  ifdef USESHADOWSAMPLER\n"
1231 "#    ifdef USESHADOWMAPPCF\n"
1232 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1233 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1234 "       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"
1235 "#    else\n"
1236 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1237 "#    endif\n"
1238 "#  else\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1241 "#      ifdef GL_ARB_texture_gather\n"
1242 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1243 "#      else\n"
1244 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1245 "#      endif\n"
1246 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1247 "#      if USESHADOWMAPPCF > 1\n"
1248 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1249 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1250 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1251 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1252 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1253 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1254 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1255 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1256 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1257 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1258 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1259 "       locols.yz += group2.ab;\n"
1260 "       hicols.yz += group8.rg;\n"
1261 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1262 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1263 "                               mix(locols, hicols, offset.y);\n"
1264 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1265 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1266 "       f = dot(cols, vec4(1.0/25.0));\n"
1267 "#      else\n"
1268 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1269 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1270 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1271 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1272 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1273 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1274 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1275 "#      endif\n"
1276 "#     else\n"
1277 "#      ifdef GL_EXT_gpu_shader4\n"
1278 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1279 "#      else\n"
1280 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1281 "#      endif\n"
1282 "#      if USESHADOWMAPPCF > 1\n"
1283 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1284 "       center *= ShadowMap_TextureScale;\n"
1285 "       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"
1286 "       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"
1287 "       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"
1288 "       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"
1289 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1290 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1291 "#      else\n"
1292 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1293 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1294 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1295 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1296 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1297 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1298 "#      endif\n"
1299 "#     endif\n"
1300 "#    else\n"
1301 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1302 "#    endif\n"
1303 "#  endif\n"
1304 "#  ifdef USESHADOWMAPORTHO\n"
1305 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1306 "#  else\n"
1307 "       return f;\n"
1308 "#  endif\n"
1309 "}\n"
1310 "# endif\n"
1311 "\n"
1312 "# ifdef USESHADOWMAPCUBE\n"
1313 "float ShadowMapCompare(vec3 dir)\n"
1314 "{\n"
1315 "       // apply depth texture cubemap as light filter\n"
1316 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1317 "       float f;\n"
1318 "#  ifdef USESHADOWSAMPLER\n"
1319 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1320 "#  else\n"
1321 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1322 "#  endif\n"
1323 "       return f;\n"
1324 "}\n"
1325 "# endif\n"
1326 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1327 "#endif // FRAGMENT_SHADER\n"
1328 "\n"
1329 "\n"
1330 "\n"
1331 "\n"
1332 "#ifdef MODE_DEFERREDGEOMETRY\n"
1333 "#ifdef VERTEX_SHADER\n"
1334 "uniform mat4 TexMatrix;\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "uniform mat4 BackgroundTexMatrix;\n"
1337 "#endif\n"
1338 "uniform mat4 ModelViewMatrix;\n"
1339 "void main(void)\n"
1340 "{\n"
1341 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1342 "#ifdef USEVERTEXTEXTUREBLEND\n"
1343 "       gl_FrontColor = gl_Color;\n"
1344 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1345 "#endif\n"
1346 "\n"
1347 "       // transform unnormalized eye direction into tangent space\n"
1348 "#ifdef USEOFFSETMAPPING\n"
1349 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1350 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1351 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1352 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1353 "#endif\n"
1354 "\n"
1355 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1356 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1357 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1358 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1359 "}\n"
1360 "#endif // VERTEX_SHADER\n"
1361 "\n"
1362 "#ifdef FRAGMENT_SHADER\n"
1363 "void main(void)\n"
1364 "{\n"
1365 "#ifdef USEOFFSETMAPPING\n"
1366 "       // apply offsetmapping\n"
1367 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1368 "#define TexCoord TexCoordOffset\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEALPHAKILL\n"
1372 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1373 "               discard;\n"
1374 "#endif\n"
1375 "\n"
1376 "#ifdef USEVERTEXTEXTUREBLEND\n"
1377 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1378 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1379 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1380 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1381 "#endif\n"
1382 "\n"
1383 "#ifdef USEVERTEXTEXTUREBLEND\n"
1384 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1385 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1386 "#else\n"
1387 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1388 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1389 "#endif\n"
1390 "\n"
1391 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1392 "}\n"
1393 "#endif // FRAGMENT_SHADER\n"
1394 "#else // !MODE_DEFERREDGEOMETRY\n"
1395 "\n"
1396 "\n"
1397 "\n"
1398 "\n"
1399 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1400 "#ifdef VERTEX_SHADER\n"
1401 "uniform mat4 ModelViewMatrix;\n"
1402 "void main(void)\n"
1403 "{\n"
1404 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "uniform mat4 ViewToLight;\n"
1411 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1412 "uniform vec2 ScreenToDepth;\n"
1413 "uniform myhalf3 DeferredColor_Ambient;\n"
1414 "uniform myhalf3 DeferredColor_Diffuse;\n"
1415 "#ifdef USESPECULAR\n"
1416 "uniform myhalf3 DeferredColor_Specular;\n"
1417 "uniform myhalf SpecularPower;\n"
1418 "#endif\n"
1419 "uniform myhalf2 PixelToScreenTexCoord;\n"
1420 "void main(void)\n"
1421 "{\n"
1422 "       // calculate viewspace pixel position\n"
1423 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1424 "       vec3 position;\n"
1425 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1426 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1427 "       // decode viewspace pixel normal\n"
1428 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1429 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1430 "       // surfacenormal = pixel normal in viewspace\n"
1431 "       // LightVector = pixel to light in viewspace\n"
1432 "       // CubeVector = position in lightspace\n"
1433 "       // eyevector = pixel to view in viewspace\n"
1434 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1435 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1436 "#ifdef USEDIFFUSE\n"
1437 "       // calculate diffuse shading\n"
1438 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1439 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1440 "#endif\n"
1441 "#ifdef USESPECULAR\n"
1442 "       // calculate directional shading\n"
1443 "       vec3 eyevector = position * -1.0;\n"
1444 "#  ifdef USEEXACTSPECULARMATH\n"
1445 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1446 "#  else\n"
1447 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1448 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1449 "#  endif\n"
1450 "#endif\n"
1451 "\n"
1452 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1453 "       fade *= ShadowMapCompare(CubeVector);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef USEDIFFUSE\n"
1457 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1458 "#else\n"
1459 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1460 "#endif\n"
1461 "#ifdef USESPECULAR\n"
1462 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1463 "#else\n"
1464 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1465 "#endif\n"
1466 "\n"
1467 "# ifdef USECUBEFILTER\n"
1468 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1469 "       gl_FragData[0].rgb *= cubecolor;\n"
1470 "       gl_FragData[1].rgb *= cubecolor;\n"
1471 "# endif\n"
1472 "}\n"
1473 "#endif // FRAGMENT_SHADER\n"
1474 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1475 "\n"
1476 "\n"
1477 "\n"
1478 "\n"
1479 "#ifdef VERTEX_SHADER\n"
1480 "uniform mat4 TexMatrix;\n"
1481 "#ifdef USEVERTEXTEXTUREBLEND\n"
1482 "uniform mat4 BackgroundTexMatrix;\n"
1483 "#endif\n"
1484 "#ifdef MODE_LIGHTSOURCE\n"
1485 "uniform mat4 ModelToLight;\n"
1486 "#endif\n"
1487 "#ifdef USESHADOWMAPORTHO\n"
1488 "uniform mat4 ShadowMapMatrix;\n"
1489 "#endif\n"
1490 "void main(void)\n"
1491 "{\n"
1492 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1493 "       gl_FrontColor = gl_Color;\n"
1494 "#endif\n"
1495 "       // copy the surface texcoord\n"
1496 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1497 "#ifdef USEVERTEXTEXTUREBLEND\n"
1498 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1499 "#endif\n"
1500 "#ifdef USELIGHTMAP\n"
1501 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef MODE_LIGHTSOURCE\n"
1505 "       // transform vertex position into light attenuation/cubemap space\n"
1506 "       // (-1 to +1 across the light box)\n"
1507 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1508 "\n"
1509 "# ifdef USEDIFFUSE\n"
1510 "       // transform unnormalized light direction into tangent space\n"
1511 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1512 "       //  normalize it per pixel)\n"
1513 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1514 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1515 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1516 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1517 "# endif\n"
1518 "#endif\n"
1519 "\n"
1520 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1521 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1522 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1523 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1524 "#endif\n"
1525 "\n"
1526 "       // transform unnormalized eye direction into tangent space\n"
1527 "#ifdef USEEYEVECTOR\n"
1528 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1529 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1530 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1531 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1532 "#endif\n"
1533 "\n"
1534 "#ifdef USEFOG\n"
1535 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1536 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1537 "#endif\n"
1538 "\n"
1539 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1540 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1541 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1542 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1543 "#endif\n"
1544 "\n"
1545 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1546 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1547 "\n"
1548 "#ifdef USESHADOWMAPORTHO\n"
1549 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1550 "#endif\n"
1551 "\n"
1552 "#ifdef USEREFLECTION\n"
1553 "       ModelViewProjectionPosition = gl_Position;\n"
1554 "#endif\n"
1555 "}\n"
1556 "#endif // VERTEX_SHADER\n"
1557 "\n"
1558 "\n"
1559 "\n"
1560 "\n"
1561 "#ifdef FRAGMENT_SHADER\n"
1562 "#ifdef USEDEFERREDLIGHTMAP\n"
1563 "uniform myhalf2 PixelToScreenTexCoord;\n"
1564 "uniform myhalf3 DeferredMod_Diffuse;\n"
1565 "uniform myhalf3 DeferredMod_Specular;\n"
1566 "#endif\n"
1567 "uniform myhalf3 Color_Ambient;\n"
1568 "uniform myhalf3 Color_Diffuse;\n"
1569 "uniform myhalf3 Color_Specular;\n"
1570 "uniform myhalf SpecularPower;\n"
1571 "#ifdef USEGLOW\n"
1572 "uniform myhalf3 Color_Glow;\n"
1573 "#endif\n"
1574 "uniform myhalf Alpha;\n"
1575 "#ifdef USEREFLECTION\n"
1576 "uniform vec4 DistortScaleRefractReflect;\n"
1577 "uniform vec4 ScreenScaleRefractReflect;\n"
1578 "uniform vec4 ScreenCenterRefractReflect;\n"
1579 "uniform myhalf4 ReflectColor;\n"
1580 "#endif\n"
1581 "#ifdef USEREFLECTCUBE\n"
1582 "uniform mat4 ModelToReflectCube;\n"
1583 "uniform sampler2D Texture_ReflectMask;\n"
1584 "uniform samplerCube Texture_ReflectCube;\n"
1585 "#endif\n"
1586 "#ifdef MODE_LIGHTDIRECTION\n"
1587 "uniform myhalf3 LightColor;\n"
1588 "#endif\n"
1589 "#ifdef MODE_LIGHTSOURCE\n"
1590 "uniform myhalf3 LightColor;\n"
1591 "#endif\n"
1592 "void main(void)\n"
1593 "{\n"
1594 "#ifdef USEOFFSETMAPPING\n"
1595 "       // apply offsetmapping\n"
1596 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1597 "#define TexCoord TexCoordOffset\n"
1598 "#endif\n"
1599 "\n"
1600 "       // combine the diffuse textures (base, pants, shirt)\n"
1601 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1602 "#ifdef USEALPHAKILL\n"
1603 "       if (color.a < 0.5)\n"
1604 "               discard;\n"
1605 "#endif\n"
1606 "       color.a *= Alpha;\n"
1607 "#ifdef USECOLORMAPPING\n"
1608 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1609 "#endif\n"
1610 "#ifdef USEVERTEXTEXTUREBLEND\n"
1611 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1612 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1613 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1614 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1615 "       color.a = 1.0;\n"
1616 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1617 "#endif\n"
1618 "\n"
1619 "       // get the surface normal\n"
1620 "#ifdef USEVERTEXTEXTUREBLEND\n"
1621 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1622 "#else\n"
1623 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1624 "#endif\n"
1625 "\n"
1626 "       // get the material colors\n"
1627 "       myhalf3 diffusetex = color.rgb;\n"
1628 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1629 "# ifdef USEVERTEXTEXTUREBLEND\n"
1630 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1631 "# else\n"
1632 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1633 "# endif\n"
1634 "#endif\n"
1635 "\n"
1636 "#ifdef USEREFLECTCUBE\n"
1637 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1638 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1639 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1640 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1641 "#endif\n"
1642 "\n"
1643 "\n"
1644 "\n"
1645 "\n"
1646 "#ifdef MODE_LIGHTSOURCE\n"
1647 "       // light source\n"
1648 "#ifdef USEDIFFUSE\n"
1649 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1650 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1651 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1652 "#ifdef USESPECULAR\n"
1653 "#ifdef USEEXACTSPECULARMATH\n"
1654 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1655 "#else\n"
1656 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1657 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1658 "#endif\n"
1659 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1660 "#endif\n"
1661 "#else\n"
1662 "       color.rgb = diffusetex * Color_Ambient;\n"
1663 "#endif\n"
1664 "       color.rgb *= LightColor;\n"
1665 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1666 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1667 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1668 "#endif\n"
1669 "# ifdef USECUBEFILTER\n"
1670 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1671 "# endif\n"
1672 "#endif // MODE_LIGHTSOURCE\n"
1673 "\n"
1674 "\n"
1675 "\n"
1676 "\n"
1677 "#ifdef MODE_LIGHTDIRECTION\n"
1678 "#define SHADING\n"
1679 "#ifdef USEDIFFUSE\n"
1680 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1681 "#endif\n"
1682 "#define lightcolor LightColor\n"
1683 "#endif // MODE_LIGHTDIRECTION\n"
1684 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1685 "#define SHADING\n"
1686 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1687 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1688 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1689 "       // convert modelspace light vector to tangentspace\n"
1690 "       myhalf3 lightnormal;\n"
1691 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1692 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1693 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1694 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1695 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1696 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1697 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1698 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1699 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1700 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1701 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1702 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1703 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1704 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1705 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1706 "#define SHADING\n"
1707 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1708 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1709 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1710 "#endif\n"
1711 "\n"
1712 "\n"
1713 "\n"
1714 "\n"
1715 "#ifdef MODE_LIGHTMAP\n"
1716 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1717 "#endif // MODE_LIGHTMAP\n"
1718 "#ifdef MODE_VERTEXCOLOR\n"
1719 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1720 "#endif // MODE_VERTEXCOLOR\n"
1721 "#ifdef MODE_FLATCOLOR\n"
1722 "       color.rgb = diffusetex * Color_Ambient;\n"
1723 "#endif // MODE_FLATCOLOR\n"
1724 "\n"
1725 "\n"
1726 "\n"
1727 "\n"
1728 "#ifdef SHADING\n"
1729 "# ifdef USEDIFFUSE\n"
1730 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1731 "#  ifdef USESPECULAR\n"
1732 "#   ifdef USEEXACTSPECULARMATH\n"
1733 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1734 "#   else\n"
1735 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1736 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1737 "#   endif\n"
1738 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1739 "#  else\n"
1740 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1741 "#  endif\n"
1742 "# else\n"
1743 "       color.rgb = diffusetex * Color_Ambient;\n"
1744 "# endif\n"
1745 "#endif\n"
1746 "\n"
1747 "#ifdef USESHADOWMAPORTHO\n"
1748 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1749 "#endif\n"
1750 "\n"
1751 "#ifdef USEDEFERREDLIGHTMAP\n"
1752 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1753 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1754 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1755 "#endif\n"
1756 "\n"
1757 "#ifdef USEGLOW\n"
1758 "#ifdef USEVERTEXTEXTUREBLEND\n"
1759 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1760 "#else\n"
1761 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1762 "#endif\n"
1763 "#endif\n"
1764 "\n"
1765 "#ifdef USEFOG\n"
1766 "       color.rgb = FogVertex(color.rgb);\n"
1767 "#endif\n"
1768 "\n"
1769 "       // 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"
1770 "#ifdef USEREFLECTION\n"
1771 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1772 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1773 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1774 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1775 "       // FIXME temporary hack to detect the case that the reflection\n"
1776 "       // gets blackened at edges due to leaving the area that contains actual\n"
1777 "       // content.\n"
1778 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1779 "       // 'appening.\n"
1780 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1781 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1782 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1783 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1784 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1785 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1786 "#endif\n"
1787 "\n"
1788 "       gl_FragColor = vec4(color);\n"
1789 "}\n"
1790 "#endif // FRAGMENT_SHADER\n"
1791 "\n"
1792 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1793 "#endif // !MODE_DEFERREDGEOMETRY\n"
1794 "#endif // !MODE_WATER\n"
1795 "#endif // !MODE_REFRACTION\n"
1796 "#endif // !MODE_BLOOMBLUR\n"
1797 "#endif // !MODE_GENERIC\n"
1798 "#endif // !MODE_POSTPROCESS\n"
1799 "#endif // !MODE_SHOWDEPTH\n"
1800 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1801 ;
1802
1803 /*
1804 =========================================================================================================================================================
1805
1806
1807
1808 =========================================================================================================================================================
1809
1810
1811
1812 =========================================================================================================================================================
1813
1814
1815
1816 =========================================================================================================================================================
1817
1818
1819
1820 =========================================================================================================================================================
1821
1822
1823
1824 =========================================================================================================================================================
1825
1826
1827
1828 =========================================================================================================================================================
1829 */
1830
1831 const char *builtincgshaderstring =
1832 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1833 "// written by Forest 'LordHavoc' Hale\n"
1834 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1835 "\n"
1836 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1837 "#if defined(USEREFLECTION)\n"
1838 "#undef USESHADOWMAPORTHO\n"
1839 "#endif\n"
1840 "\n"
1841 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1842 "# define USEFOG\n"
1843 "#endif\n"
1844 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1845 "#define USELIGHTMAP\n"
1846 "#endif\n"
1847 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1848 "#define USEEYEVECTOR\n"
1849 "#endif\n"
1850 "\n"
1851 "#ifdef FRAGMENT_SHADER\n"
1852 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#endif\n"
1854 "\n"
1855 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1856 "#ifdef VERTEX_SHADER\n"
1857 "void main\n"
1858 "(\n"
1859 "float4 gl_Vertex : POSITION,\n"
1860 "uniform float4x4 ModelViewProjectionMatrix,\n"
1861 "out float4 gl_Position : POSITION\n"
1862 ")\n"
1863 "{\n"
1864 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1865 "}\n"
1866 "#endif\n"
1867 "#else // !MODE_DEPTH_ORSHADOW\n"
1868 "\n"
1869 "\n"
1870 "\n"
1871 "\n"
1872 "#ifdef MODE_SHOWDEPTH\n"
1873 "#ifdef VERTEX_SHADER\n"
1874 "void main\n"
1875 "(\n"
1876 "float4 gl_Vertex : POSITION,\n"
1877 "uniform float4x4 ModelViewProjectionMatrix,\n"
1878 "out float4 gl_Position : POSITION,\n"
1879 "out float4 gl_FrontColor : COLOR0\n"
1880 ")\n"
1881 "{\n"
1882 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1883 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1884 "}\n"
1885 "#endif\n"
1886 "\n"
1887 "#ifdef FRAGMENT_SHADER\n"
1888 "void main\n"
1889 "(\n"
1890 "float4 gl_FrontColor : COLOR0,\n"
1891 "out float4 gl_FragColor : COLOR\n"
1892 ")\n"
1893 "{\n"
1894 "       gl_FragColor = gl_FrontColor;\n"
1895 "}\n"
1896 "#endif\n"
1897 "#else // !MODE_SHOWDEPTH\n"
1898 "\n"
1899 "\n"
1900 "\n"
1901 "\n"
1902 "#ifdef MODE_POSTPROCESS\n"
1903 "\n"
1904 "#ifdef VERTEX_SHADER\n"
1905 "void main\n"
1906 "(\n"
1907 "float4 gl_Vertex : POSITION,\n"
1908 "uniform float4x4 ModelViewProjectionMatrix,\n"
1909 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1910 "float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
1911 "out float4 gl_Position : POSITION,\n"
1912 "out float2 TexCoord1 : TEXCOORD0,\n"
1913 "out float2 TexCoord2 : TEXCOORD1\n"
1914 ")\n"
1915 "{\n"
1916 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1917 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1918 "#ifdef USEBLOOM\n"
1919 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1920 "#endif\n"
1921 "}\n"
1922 "#endif\n"
1923 "\n"
1924 "#ifdef FRAGMENT_SHADER\n"
1925 "void main\n"
1926 "(\n"
1927 "float2 TexCoord1 : TEXCOORD0,\n"
1928 "float2 TexCoord2 : TEXCOORD1,\n"
1929 "uniform sampler2D Texture_First,\n"
1930 "#ifdef USEBLOOM\n"
1931 "uniform sampler2D Texture_Second,\n"
1932 "#endif\n"
1933 "#ifdef USEGAMMARAMPS\n"
1934 "uniform sampler2D Texture_GammaRamps,\n"
1935 "#endif\n"
1936 "#ifdef USESATURATION\n"
1937 "uniform float Saturation,\n"
1938 "#endif\n"
1939 "#ifdef USEVIEWTINT\n"
1940 "uniform float4 ViewTintColor,\n"
1941 "#endif\n"
1942 "uniform float4 UserVec1,\n"
1943 "uniform float4 UserVec2,\n"
1944 "uniform float4 UserVec3,\n"
1945 "uniform float4 UserVec4,\n"
1946 "uniform float ClientTime,\n"
1947 "uniform float2 PixelSize,\n"
1948 "out float4 gl_FragColor : COLOR\n"
1949 ")\n"
1950 "{\n"
1951 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1952 "#ifdef USEBLOOM\n"
1953 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1954 "#endif\n"
1955 "#ifdef USEVIEWTINT\n"
1956 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1957 "#endif\n"
1958 "\n"
1959 "#ifdef USEPOSTPROCESSING\n"
1960 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1961 "// 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"
1962 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1963 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1964 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1965 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1966 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1967 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
1968 "#endif\n"
1969 "\n"
1970 "#ifdef USESATURATION\n"
1971 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1972 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1973 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1974 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
1975 "#endif\n"
1976 "\n"
1977 "#ifdef USEGAMMARAMPS\n"
1978 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1979 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1980 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1981 "#endif\n"
1982 "}\n"
1983 "#endif\n"
1984 "#else // !MODE_POSTPROCESS\n"
1985 "\n"
1986 "\n"
1987 "\n"
1988 "\n"
1989 "#ifdef MODE_GENERIC\n"
1990 "#ifdef VERTEX_SHADER\n"
1991 "void main\n"
1992 "(\n"
1993 "float4 gl_Vertex : POSITION,\n"
1994 "uniform float4x4 ModelViewProjectionMatrix,\n"
1995 "float4 gl_Color : COLOR0,\n"
1996 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1997 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
1998 "out float4 gl_Position : POSITION,\n"
1999 "out float4 gl_FrontColor : COLOR,\n"
2000 "out float2 TexCoord1 : TEXCOORD0,\n"
2001 "out float2 TexCoord2 : TEXCOORD1\n"
2002 ")\n"
2003 "{\n"
2004 "       gl_FrontColor = gl_Color;\n"
2005 "#ifdef USEDIFFUSE\n"
2006 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2007 "#endif\n"
2008 "#ifdef USESPECULAR\n"
2009 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2010 "#endif\n"
2011 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2012 "}\n"
2013 "#endif\n"
2014 "\n"
2015 "#ifdef FRAGMENT_SHADER\n"
2016 "\n"
2017 "void main\n"
2018 "(\n"
2019 "float4 gl_FrontColor : COLOR,\n"
2020 "float2 TexCoord1 : TEXCOORD0,\n"
2021 "float2 TexCoord2 : TEXCOORD1,\n"
2022 "#ifdef USEDIFFUSE\n"
2023 "uniform sampler2D Texture_First,\n"
2024 "#endif\n"
2025 "#ifdef USESPECULAR\n"
2026 "uniform sampler2D Texture_Second,\n"
2027 "#endif\n"
2028 "out float4 gl_FragColor : COLOR\n"
2029 ")\n"
2030 "{\n"
2031 "       gl_FragColor = gl_FrontColor;\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2034 "#endif\n"
2035 "\n"
2036 "#ifdef USESPECULAR\n"
2037 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2038 "# ifdef USECOLORMAPPING\n"
2039 "       gl_FragColor *= tex2;\n"
2040 "# endif\n"
2041 "# ifdef USEGLOW\n"
2042 "       gl_FragColor += tex2;\n"
2043 "# endif\n"
2044 "# ifdef USEVERTEXTEXTUREBLEND\n"
2045 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2046 "# endif\n"
2047 "#endif\n"
2048 "}\n"
2049 "#endif\n"
2050 "#else // !MODE_GENERIC\n"
2051 "\n"
2052 "\n"
2053 "\n"
2054 "\n"
2055 "#ifdef MODE_BLOOMBLUR\n"
2056 "#ifdef VERTEX_SHADER\n"
2057 "void main\n"
2058 "(\n"
2059 "float4 gl_Vertex : POSITION,\n"
2060 "uniform float4x4 ModelViewProjectionMatrix,\n"
2061 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2062 "out float4 gl_Position : POSITION,\n"
2063 "out float2 TexCoord : TEXCOORD0\n"
2064 ")\n"
2065 "{\n"
2066 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2067 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2068 "}\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef FRAGMENT_SHADER\n"
2072 "\n"
2073 "void main\n"
2074 "(\n"
2075 "float2 TexCoord : TEXCOORD0,\n"
2076 "uniform sampler2D Texture_First,\n"
2077 "uniform float4 BloomBlur_Parameters,\n"
2078 "out float4 gl_FragColor : COLOR\n"
2079 ")\n"
2080 "{\n"
2081 "       int i;\n"
2082 "       float2 tc = TexCoord;\n"
2083 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2084 "       tc += BloomBlur_Parameters.xy;\n"
2085 "       for (i = 1;i < SAMPLES;i++)\n"
2086 "       {\n"
2087 "               color += tex2D(Texture_First, tc).rgb;\n"
2088 "               tc += BloomBlur_Parameters.xy;\n"
2089 "       }\n"
2090 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2091 "}\n"
2092 "#endif\n"
2093 "#else // !MODE_BLOOMBLUR\n"
2094 "#ifdef MODE_REFRACTION\n"
2095 "#ifdef VERTEX_SHADER\n"
2096 "void main\n"
2097 "(\n"
2098 "float4 gl_Vertex : POSITION,\n"
2099 "uniform float4x4 ModelViewProjectionMatrix,\n"
2100 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2101 "uniform float4x4 TexMatrix,\n"
2102 "uniform float3 EyePosition,\n"
2103 "out float4 gl_Position : POSITION,\n"
2104 "out float2 TexCoord : TEXCOORD0,\n"
2105 "out float3 EyeVector : TEXCOORD1,\n"
2106 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2107 ")\n"
2108 "{\n"
2109 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2110 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2111 "       ModelViewProjectionPosition = gl_Position;\n"
2112 "}\n"
2113 "#endif\n"
2114 "\n"
2115 "#ifdef FRAGMENT_SHADER\n"
2116 "void main\n"
2117 "(\n"
2118 "float2 TexCoord : TEXCOORD0,\n"
2119 "float3 EyeVector : TEXCOORD1,\n"
2120 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2121 "uniform sampler2D Texture_Normal,\n"
2122 "uniform sampler2D Texture_Refraction,\n"
2123 "uniform sampler2D Texture_Reflection,\n"
2124 "uniform float4 DistortScaleRefractReflect,\n"
2125 "uniform float4 ScreenScaleRefractReflect,\n"
2126 "uniform float4 ScreenCenterRefractReflect,\n"
2127 "uniform float4 RefractColor,\n"
2128 "out float4 gl_FragColor : COLOR\n"
2129 ")\n"
2130 "{\n"
2131 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2132 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2133 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2134 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2135 "       // FIXME temporary hack to detect the case that the reflection\n"
2136 "       // gets blackened at edges due to leaving the area that contains actual\n"
2137 "       // content.\n"
2138 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2139 "       // 'appening.\n"
2140 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2141 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2142 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2143 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2144 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2145 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2146 "}\n"
2147 "#endif\n"
2148 "#else // !MODE_REFRACTION\n"
2149 "\n"
2150 "\n"
2151 "\n"
2152 "\n"
2153 "#ifdef MODE_WATER\n"
2154 "#ifdef VERTEX_SHADER\n"
2155 "\n"
2156 "void main\n"
2157 "(\n"
2158 "float4 gl_Vertex : POSITION,\n"
2159 "uniform float4x4 ModelViewProjectionMatrix,\n"
2160 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2161 "uniform float4x4 TexMatrix,\n"
2162 "uniform float3 EyePosition,\n"
2163 "out float4 gl_Position : POSITION,\n"
2164 "out float2 TexCoord : TEXCOORD0,\n"
2165 "out float3 EyeVector : TEXCOORD1,\n"
2166 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2167 ")\n"
2168 "{\n"
2169 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2170 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2171 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2172 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2173 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2174 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2175 "       ModelViewProjectionPosition = gl_Position;\n"
2176 "}\n"
2177 "#endif\n"
2178 "\n"
2179 "#ifdef FRAGMENT_SHADER\n"
2180 "void main\n"
2181 "(\n"
2182 "float2 TexCoord : TEXCOORD0,\n"
2183 "float3 EyeVector : TEXCOORD1,\n"
2184 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2185 "uniform sampler2D Texture_Normal,\n"
2186 "uniform sampler2D Texture_Refraction,\n"
2187 "uniform sampler2D Texture_Reflection,\n"
2188 "uniform float4 DistortScaleRefractReflect,\n"
2189 "uniform float4 ScreenScaleRefractReflect,\n"
2190 "uniform float4 ScreenCenterRefractReflect,\n"
2191 "uniform float4 RefractColor,\n"
2192 "uniform float4 ReflectColor,\n"
2193 "uniform float ReflectFactor,\n"
2194 "uniform float ReflectOffset,\n"
2195 "out float4 gl_FragColor : COLOR\n"
2196 ")\n"
2197 "{\n"
2198 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2199 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2200 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2201 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2202 "       // FIXME temporary hack to detect the case that the reflection\n"
2203 "       // gets blackened at edges due to leaving the area that contains actual\n"
2204 "       // content.\n"
2205 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2206 "       // 'appening.\n"
2207 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2208 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2209 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2210 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2211 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2212 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2217 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2218 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2219 "}\n"
2220 "#endif\n"
2221 "#else // !MODE_WATER\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "\n"
2226 "// 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"
2227 "\n"
2228 "// fragment shader specific:\n"
2229 "#ifdef FRAGMENT_SHADER\n"
2230 "\n"
2231 "#ifdef USEFOG\n"
2232 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2233 "{\n"
2234 "       float fogfrac;\n"
2235 "#ifdef USEFOGHEIGHTTEXTURE\n"
2236 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2237 "       fogfrac = fogheightpixel.a;\n"
2238 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2239 "#else\n"
2240 "# ifdef USEFOGOUTSIDE\n"
2241 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2242 "# else\n"
2243 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2244 "# endif\n"
2245 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2246 "#endif\n"
2247 "}\n"
2248 "#endif\n"
2249 "\n"
2250 "#ifdef USEOFFSETMAPPING\n"
2251 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2252 "{\n"
2253 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2254 "       // 14 sample relief mapping: linear search and then binary search\n"
2255 "       // this basically steps forward a small amount repeatedly until it finds\n"
2256 "       // itself inside solid, then jitters forward and back using decreasing\n"
2257 "       // amounts to find the impact\n"
2258 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2259 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2260 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2261 "       float3 RT = float3(TexCoord, 1);\n"
2262 "       OffsetVector *= 0.1;\n"
2263 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2264 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2265 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2266 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2267 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2268 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2269 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2270 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2271 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2272 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2273 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2274 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2275 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2276 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2277 "       return RT.xy;\n"
2278 "#else\n"
2279 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2280 "       // this basically moves forward the full distance, and then backs up based\n"
2281 "       // on height of samples\n"
2282 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2283 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2284 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2285 "       TexCoord += OffsetVector;\n"
2286 "       OffsetVector *= 0.333;\n"
2287 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2288 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2289 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2290 "       return TexCoord;\n"
2291 "#endif\n"
2292 "}\n"
2293 "#endif // USEOFFSETMAPPING\n"
2294 "\n"
2295 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2296 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2297 "# ifdef USESHADOWMAPORTHO\n"
2298 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2299 "# else\n"
2300 "#  ifdef USESHADOWMAPVSDCT\n"
2301 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2302 "{\n"
2303 "       float3 adir = abs(dir);\n"
2304 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2305 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2306 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2307 "}\n"
2308 "#  else\n"
2309 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2310 "{\n"
2311 "       float3 adir = abs(dir);\n"
2312 "       float ma = adir.z;\n"
2313 "       float4 proj = float4(dir, 2.5);\n"
2314 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2315 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2316 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2317 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2318 "}\n"
2319 "#  endif\n"
2320 "# endif\n"
2321 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2322 "\n"
2323 "#ifdef USESHADOWMAPCUBE\n"
2324 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2325 "{\n"
2326 "    float3 adir = abs(dir);\n"
2327 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2328 "}\n"
2329 "#endif\n"
2330 "\n"
2331 "# ifdef USESHADOWMAPRECT\n"
2332 "#ifdef USESHADOWMAPVSDCT\n"
2333 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2334 "#else\n"
2335 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\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 "#  ifdef USESHADOWSAMPLER\n"
2345 "\n"
2346 "#    ifdef USESHADOWMAPPCF\n"
2347 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2348 "    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"
2349 "#    else\n"
2350 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2351 "#    endif\n"
2352 "\n"
2353 "#  else\n"
2354 "\n"
2355 "#    ifdef USESHADOWMAPPCF\n"
2356 "#      if USESHADOWMAPPCF > 1\n"
2357 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2358 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2359 "    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"
2360 "    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"
2361 "    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"
2362 "    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"
2363 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2364 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2365 "#      else\n"
2366 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2367 "    float2 offset = frac(shadowmaptc.xy);\n"
2368 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2369 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2370 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2371 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2372 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2373 "#      endif\n"
2374 "#    else\n"
2375 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2376 "#    endif\n"
2377 "\n"
2378 "#  endif\n"
2379 "#  ifdef USESHADOWMAPORTHO\n"
2380 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2381 "#  else\n"
2382 "       return f;\n"
2383 "#  endif\n"
2384 "}\n"
2385 "# endif\n"
2386 "\n"
2387 "# ifdef USESHADOWMAP2D\n"
2388 "#ifdef USESHADOWMAPVSDCT\n"
2389 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2390 "#else\n"
2391 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2392 "#endif\n"
2393 "{\n"
2394 "#ifdef USESHADOWMAPVSDCT\n"
2395 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2396 "#else\n"
2397 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2398 "#endif\n"
2399 "    float f;\n"
2400 "\n"
2401 "#  ifdef USESHADOWSAMPLER\n"
2402 "#    ifdef USESHADOWMAPPCF\n"
2403 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2404 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2405 "    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"
2406 "#    else\n"
2407 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2408 "#    endif\n"
2409 "#  else\n"
2410 "#    ifdef USESHADOWMAPPCF\n"
2411 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2412 "#      ifdef GL_ARB_texture_gather\n"
2413 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2414 "#      else\n"
2415 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2416 "#      endif\n"
2417 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2418 "    center *= ShadowMap_TextureScale;\n"
2419 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2420 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2421 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2422 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2423 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2424 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2425 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2426 "#     else\n"
2427 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2428 "#      if USESHADOWMAPPCF > 1\n"
2429 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2430 "    center *= ShadowMap_TextureScale;\n"
2431 "    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"
2432 "    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"
2433 "    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"
2434 "    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"
2435 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2436 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2437 "#      else\n"
2438 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2439 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2440 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2441 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2442 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2443 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2444 "#      endif\n"
2445 "#     endif\n"
2446 "#    else\n"
2447 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2448 "#    endif\n"
2449 "#  endif\n"
2450 "#  ifdef USESHADOWMAPORTHO\n"
2451 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2452 "#  else\n"
2453 "       return f;\n"
2454 "#  endif\n"
2455 "}\n"
2456 "# endif\n"
2457 "\n"
2458 "# ifdef USESHADOWMAPCUBE\n"
2459 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2460 "{\n"
2461 "    // apply depth texture cubemap as light filter\n"
2462 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2463 "    float f;\n"
2464 "#  ifdef USESHADOWSAMPLER\n"
2465 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2466 "#  else\n"
2467 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2468 "#  endif\n"
2469 "    return f;\n"
2470 "}\n"
2471 "# endif\n"
2472 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2473 "#endif // FRAGMENT_SHADER\n"
2474 "\n"
2475 "\n"
2476 "\n"
2477 "\n"
2478 "#ifdef MODE_DEFERREDGEOMETRY\n"
2479 "#ifdef VERTEX_SHADER\n"
2480 "void main\n"
2481 "(\n"
2482 "float4 gl_Vertex : POSITION,\n"
2483 "uniform float4x4 ModelViewProjectionMatrix,\n"
2484 "#ifdef USEVERTEXTEXTUREBLEND\n"
2485 "float4 gl_Color : COLOR0,\n"
2486 "#endif\n"
2487 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2488 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2489 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2490 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2491 "uniform float4x4 TexMatrix,\n"
2492 "#ifdef USEVERTEXTEXTUREBLEND\n"
2493 "uniform float4x4 BackgroundTexMatrix,\n"
2494 "#endif\n"
2495 "uniform float4x4 ModelViewMatrix,\n"
2496 "#ifdef USEOFFSETMAPPING\n"
2497 "uniform float3 EyePosition,\n"
2498 "#endif\n"
2499 "out float4 gl_Position : POSITION,\n"
2500 "out float4 gl_FrontColor : COLOR,\n"
2501 "out float4 TexCoordBoth : TEXCOORD0,\n"
2502 "#ifdef USEOFFSETMAPPING\n"
2503 "out float3 EyeVector : TEXCOORD2,\n"
2504 "#endif\n"
2505 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2506 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2507 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2508 ")\n"
2509 "{\n"
2510 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2511 "#ifdef USEVERTEXTEXTUREBLEND\n"
2512 "       gl_FrontColor = gl_Color;\n"
2513 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2514 "#endif\n"
2515 "\n"
2516 "       // transform unnormalized eye direction into tangent space\n"
2517 "#ifdef USEOFFSETMAPPING\n"
2518 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2519 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2520 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2521 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2522 "#endif\n"
2523 "\n"
2524 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2525 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2526 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2527 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2528 "}\n"
2529 "#endif // VERTEX_SHADER\n"
2530 "\n"
2531 "#ifdef FRAGMENT_SHADER\n"
2532 "void main\n"
2533 "(\n"
2534 "float4 TexCoordBoth : TEXCOORD0,\n"
2535 "float3 EyeVector : TEXCOORD2,\n"
2536 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2537 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2538 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2539 "uniform sampler2D Texture_Normal,\n"
2540 "#ifdef USEALPHAKILL\n"
2541 "uniform sampler2D Texture_Color,\n"
2542 "#endif\n"
2543 "uniform sampler2D Texture_Gloss,\n"
2544 "#ifdef USEVERTEXTEXTUREBLEND\n"
2545 "uniform sampler2D Texture_SecondaryNormal,\n"
2546 "uniform sampler2D Texture_SecondaryGloss,\n"
2547 "#endif\n"
2548 "#ifdef USEOFFSETMAPPING\n"
2549 "uniform float OffsetMapping_Scale,\n"
2550 "#endif\n"
2551 "uniform half SpecularPower,\n"
2552 "out float4 gl_FragColor : COLOR\n"
2553 ")\n"
2554 "{\n"
2555 "       float2 TexCoord = TexCoordBoth.xy;\n"
2556 "#ifdef USEOFFSETMAPPING\n"
2557 "       // apply offsetmapping\n"
2558 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2559 "#define TexCoord TexCoordOffset\n"
2560 "#endif\n"
2561 "\n"
2562 "#ifdef USEALPHAKILL\n"
2563 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2564 "               discard;\n"
2565 "#endif\n"
2566 "\n"
2567 "#ifdef USEVERTEXTEXTUREBLEND\n"
2568 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2569 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2570 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2571 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2572 "#endif\n"
2573 "\n"
2574 "#ifdef USEVERTEXTEXTUREBLEND\n"
2575 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2576 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2577 "#else\n"
2578 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2579 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2580 "#endif\n"
2581 "\n"
2582 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2583 "}\n"
2584 "#endif // FRAGMENT_SHADER\n"
2585 "#else // !MODE_DEFERREDGEOMETRY\n"
2586 "\n"
2587 "\n"
2588 "\n"
2589 "\n"
2590 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2591 "#ifdef VERTEX_SHADER\n"
2592 "void main\n"
2593 "(\n"
2594 "float4 gl_Vertex : POSITION,\n"
2595 "uniform float4x4 ModelViewProjectionMatrix,\n"
2596 "uniform float4x4 ModelViewMatrix,\n"
2597 "out float4 gl_Position : POSITION,\n"
2598 "out float4 ModelViewPosition : TEXCOORD0\n"
2599 ")\n"
2600 "{\n"
2601 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2602 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2603 "}\n"
2604 "#endif // VERTEX_SHADER\n"
2605 "\n"
2606 "#ifdef FRAGMENT_SHADER\n"
2607 "void main\n"
2608 "(\n"
2609 "float2 Pixel : WPOS,\n"
2610 "float4 ModelViewPosition : TEXCOORD0,\n"
2611 "uniform float4x4 ViewToLight,\n"
2612 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2613 "uniform float3 LightPosition,\n"
2614 "uniform half2 PixelToScreenTexCoord,\n"
2615 "uniform half3 DeferredColor_Ambient,\n"
2616 "uniform half3 DeferredColor_Diffuse,\n"
2617 "#ifdef USESPECULAR\n"
2618 "uniform half3 DeferredColor_Specular,\n"
2619 "uniform half SpecularPower,\n"
2620 "#endif\n"
2621 "uniform sampler2D Texture_Attenuation,\n"
2622 "uniform sampler2D Texture_ScreenDepth,\n"
2623 "uniform sampler2D Texture_ScreenNormalMap,\n"
2624 "\n"
2625 "#ifdef USECUBEFILTER\n"
2626 "uniform samplerCUBE Texture_Cube,\n"
2627 "#endif\n"
2628 "\n"
2629 "#ifdef USESHADOWMAPRECT\n"
2630 "# ifdef USESHADOWSAMPLER\n"
2631 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2632 "# else\n"
2633 "uniform samplerRECT Texture_ShadowMapRect,\n"
2634 "# endif\n"
2635 "#endif\n"
2636 "\n"
2637 "#ifdef USESHADOWMAP2D\n"
2638 "# ifdef USESHADOWSAMPLER\n"
2639 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2640 "# else\n"
2641 "uniform sampler2D Texture_ShadowMap2D,\n"
2642 "# endif\n"
2643 "#endif\n"
2644 "\n"
2645 "#ifdef USESHADOWMAPVSDCT\n"
2646 "uniform samplerCUBE Texture_CubeProjection,\n"
2647 "#endif\n"
2648 "\n"
2649 "#ifdef USESHADOWMAPCUBE\n"
2650 "# ifdef USESHADOWSAMPLER\n"
2651 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2652 "# else\n"
2653 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2654 "# endif\n"
2655 "#endif\n"
2656 "\n"
2657 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2658 "uniform float2 ShadowMap_TextureScale,\n"
2659 "uniform float4 ShadowMap_Parameters,\n"
2660 "#endif\n"
2661 "\n"
2662 "out float4 gl_FragData0 : COLOR0,\n"
2663 "out float4 gl_FragData1 : COLOR1\n"
2664 ")\n"
2665 "{\n"
2666 "       // calculate viewspace pixel position\n"
2667 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2668 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2669 "       float3 position;\n"
2670 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2671 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2672 "       // decode viewspace pixel normal\n"
2673 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2674 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2675 "       // surfacenormal = pixel normal in viewspace\n"
2676 "       // LightVector = pixel to light in viewspace\n"
2677 "       // CubeVector = position in lightspace\n"
2678 "       // eyevector = pixel to view in viewspace\n"
2679 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2680 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2681 "#ifdef USEDIFFUSE\n"
2682 "       // calculate diffuse shading\n"
2683 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2684 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2685 "#endif\n"
2686 "#ifdef USESPECULAR\n"
2687 "       // calculate directional shading\n"
2688 "       float3 eyevector = position * -1.0;\n"
2689 "#  ifdef USEEXACTSPECULARMATH\n"
2690 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2691 "#  else\n"
2692 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2693 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2694 "#  endif\n"
2695 "#endif\n"
2696 "\n"
2697 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2698 "       fade *= ShadowMapCompare(CubeVector,\n"
2699 "# if defined(USESHADOWMAP2D)\n"
2700 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2701 "# endif\n"
2702 "# if defined(USESHADOWMAPRECT)\n"
2703 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2704 "# endif\n"
2705 "# if defined(USESHADOWMAPCUBE)\n"
2706 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2707 "# endif\n"
2708 "\n"
2709 "#ifdef USESHADOWMAPVSDCT\n"
2710 ", Texture_CubeProjection\n"
2711 "#endif\n"
2712 "       );\n"
2713 "#endif\n"
2714 "\n"
2715 "#ifdef USEDIFFUSE\n"
2716 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2717 "#else\n"
2718 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2719 "#endif\n"
2720 "#ifdef USESPECULAR\n"
2721 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2722 "#else\n"
2723 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2724 "#endif\n"
2725 "\n"
2726 "# ifdef USECUBEFILTER\n"
2727 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2728 "       gl_FragData0.rgb *= cubecolor;\n"
2729 "       gl_FragData1.rgb *= cubecolor;\n"
2730 "# endif\n"
2731 "}\n"
2732 "#endif // FRAGMENT_SHADER\n"
2733 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2734 "\n"
2735 "\n"
2736 "\n"
2737 "\n"
2738 "#ifdef VERTEX_SHADER\n"
2739 "void main\n"
2740 "(\n"
2741 "float4 gl_Vertex : POSITION,\n"
2742 "uniform float4x4 ModelViewProjectionMatrix,\n"
2743 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2744 "float4 gl_Color : COLOR0,\n"
2745 "#endif\n"
2746 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2747 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2748 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2749 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2750 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2751 "\n"
2752 "uniform float3 EyePosition,\n"
2753 "uniform float4x4 TexMatrix,\n"
2754 "#ifdef USEVERTEXTEXTUREBLEND\n"
2755 "uniform float4x4 BackgroundTexMatrix,\n"
2756 "#endif\n"
2757 "#ifdef MODE_LIGHTSOURCE\n"
2758 "uniform float4x4 ModelToLight,\n"
2759 "#endif\n"
2760 "#ifdef MODE_LIGHTSOURCE\n"
2761 "uniform float3 LightPosition,\n"
2762 "#endif\n"
2763 "#ifdef MODE_LIGHTDIRECTION\n"
2764 "uniform float3 LightDir,\n"
2765 "#endif\n"
2766 "uniform float4 FogPlane,\n"
2767 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2768 "uniform float3 LightPosition,\n"
2769 "#endif\n"
2770 "#ifdef USESHADOWMAPORTHO\n"
2771 "uniform float4x4 ShadowMapMatrix,\n"
2772 "#endif\n"
2773 "\n"
2774 "out float4 gl_FrontColor : COLOR,\n"
2775 "out float4 TexCoordBoth : TEXCOORD0,\n"
2776 "#ifdef USELIGHTMAP\n"
2777 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2778 "#endif\n"
2779 "#ifdef USEEYEVECTOR\n"
2780 "out float3 EyeVector : TEXCOORD2,\n"
2781 "#endif\n"
2782 "#ifdef USEREFLECTION\n"
2783 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2784 "#endif\n"
2785 "#ifdef USEFOG\n"
2786 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2787 "#endif\n"
2788 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2789 "out float3 LightVector : TEXCOORD1,\n"
2790 "#endif\n"
2791 "#ifdef MODE_LIGHTSOURCE\n"
2792 "out float3 CubeVector : TEXCOORD3,\n"
2793 "#endif\n"
2794 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2795 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2796 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2797 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2801 "#endif\n"
2802 "out float4 gl_Position : POSITION\n"
2803 ")\n"
2804 "{\n"
2805 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2806 "       gl_FrontColor = gl_Color;\n"
2807 "#endif\n"
2808 "       // copy the surface texcoord\n"
2809 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2810 "#ifdef USEVERTEXTEXTUREBLEND\n"
2811 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2812 "#endif\n"
2813 "#ifdef USELIGHTMAP\n"
2814 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2815 "#endif\n"
2816 "\n"
2817 "#ifdef MODE_LIGHTSOURCE\n"
2818 "       // transform vertex position into light attenuation/cubemap space\n"
2819 "       // (-1 to +1 across the light box)\n"
2820 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2821 "\n"
2822 "# ifdef USEDIFFUSE\n"
2823 "       // transform unnormalized light direction into tangent space\n"
2824 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2825 "       //  normalize it per pixel)\n"
2826 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2827 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2828 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2829 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2830 "# endif\n"
2831 "#endif\n"
2832 "\n"
2833 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2834 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2835 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2836 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2837 "#endif\n"
2838 "\n"
2839 "       // transform unnormalized eye direction into tangent space\n"
2840 "#ifdef USEEYEVECTOR\n"
2841 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2842 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2843 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2844 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2845 "#endif\n"
2846 "\n"
2847 "#ifdef USEFOG\n"
2848 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2849 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2850 "#endif\n"
2851 "\n"
2852 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2853 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2854 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2855 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2856 "#endif\n"
2857 "\n"
2858 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2859 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2860 "\n"
2861 "#ifdef USESHADOWMAPORTHO\n"
2862 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2863 "#endif\n"
2864 "\n"
2865 "#ifdef USEREFLECTION\n"
2866 "       ModelViewProjectionPosition = gl_Position;\n"
2867 "#endif\n"
2868 "}\n"
2869 "#endif // VERTEX_SHADER\n"
2870 "\n"
2871 "\n"
2872 "\n"
2873 "\n"
2874 "#ifdef FRAGMENT_SHADER\n"
2875 "void main\n"
2876 "(\n"
2877 "#ifdef USEDEFERREDLIGHTMAP\n"
2878 "float2 Pixel : WPOS,\n"
2879 "#endif\n"
2880 "float4 gl_FrontColor : COLOR,\n"
2881 "float4 TexCoordBoth : TEXCOORD0,\n"
2882 "#ifdef USELIGHTMAP\n"
2883 "float2 TexCoordLightmap : TEXCOORD1,\n"
2884 "#endif\n"
2885 "#ifdef USEEYEVECTOR\n"
2886 "float3 EyeVector : TEXCOORD2,\n"
2887 "#endif\n"
2888 "#ifdef USEREFLECTION\n"
2889 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2890 "#endif\n"
2891 "#ifdef USEFOG\n"
2892 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2893 "#endif\n"
2894 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2895 "float3 LightVector : TEXCOORD1,\n"
2896 "#endif\n"
2897 "#ifdef MODE_LIGHTSOURCE\n"
2898 "float3 CubeVector : TEXCOORD3,\n"
2899 "#endif\n"
2900 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2901 "float4 ModelViewPosition : TEXCOORD0,\n"
2902 "#endif\n"
2903 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2904 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2905 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2906 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2907 "#endif\n"
2908 "#ifdef USESHADOWMAPORTHO\n"
2909 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2910 "#endif\n"
2911 "\n"
2912 "uniform sampler2D Texture_Normal,\n"
2913 "uniform sampler2D Texture_Color,\n"
2914 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2915 "uniform sampler2D Texture_Gloss,\n"
2916 "#endif\n"
2917 "#ifdef USEGLOW\n"
2918 "uniform sampler2D Texture_Glow,\n"
2919 "#endif\n"
2920 "#ifdef USEVERTEXTEXTUREBLEND\n"
2921 "uniform sampler2D Texture_SecondaryNormal,\n"
2922 "uniform sampler2D Texture_SecondaryColor,\n"
2923 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2924 "uniform sampler2D Texture_SecondaryGloss,\n"
2925 "#endif\n"
2926 "#ifdef USEGLOW\n"
2927 "uniform sampler2D Texture_SecondaryGlow,\n"
2928 "#endif\n"
2929 "#endif\n"
2930 "#ifdef USECOLORMAPPING\n"
2931 "uniform sampler2D Texture_Pants,\n"
2932 "uniform sampler2D Texture_Shirt,\n"
2933 "#endif\n"
2934 "#ifdef USEFOG\n"
2935 "uniform sampler2D Texture_FogHeightTexture,\n"
2936 "uniform sampler2D Texture_FogMask,\n"
2937 "#endif\n"
2938 "#ifdef USELIGHTMAP\n"
2939 "uniform sampler2D Texture_Lightmap,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2942 "uniform sampler2D Texture_Deluxemap,\n"
2943 "#endif\n"
2944 "#ifdef USEREFLECTION\n"
2945 "uniform sampler2D Texture_Reflection,\n"
2946 "#endif\n"
2947 "\n"
2948 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2949 "uniform sampler2D Texture_ScreenDepth,\n"
2950 "uniform sampler2D Texture_ScreenNormalMap,\n"
2951 "#endif\n"
2952 "#ifdef USEDEFERREDLIGHTMAP\n"
2953 "uniform sampler2D Texture_ScreenDiffuse,\n"
2954 "uniform sampler2D Texture_ScreenSpecular,\n"
2955 "#endif\n"
2956 "\n"
2957 "#ifdef USECOLORMAPPING\n"
2958 "uniform half3 Color_Pants,\n"
2959 "uniform half3 Color_Shirt,\n"
2960 "#endif\n"
2961 "#ifdef USEFOG\n"
2962 "uniform float3 FogColor,\n"
2963 "uniform float FogRangeRecip,\n"
2964 "uniform float FogPlaneViewDist,\n"
2965 "uniform float FogHeightFade,\n"
2966 "#endif\n"
2967 "\n"
2968 "#ifdef USEOFFSETMAPPING\n"
2969 "uniform float OffsetMapping_Scale,\n"
2970 "#endif\n"
2971 "\n"
2972 "#ifdef USEDEFERREDLIGHTMAP\n"
2973 "uniform half2 PixelToScreenTexCoord,\n"
2974 "uniform half3 DeferredMod_Diffuse,\n"
2975 "uniform half3 DeferredMod_Specular,\n"
2976 "#endif\n"
2977 "uniform half3 Color_Ambient,\n"
2978 "uniform half3 Color_Diffuse,\n"
2979 "uniform half3 Color_Specular,\n"
2980 "uniform half SpecularPower,\n"
2981 "#ifdef USEGLOW\n"
2982 "uniform half3 Color_Glow,\n"
2983 "#endif\n"
2984 "uniform half Alpha,\n"
2985 "#ifdef USEREFLECTION\n"
2986 "uniform float4 DistortScaleRefractReflect,\n"
2987 "uniform float4 ScreenScaleRefractReflect,\n"
2988 "uniform float4 ScreenCenterRefractReflect,\n"
2989 "uniform half4 ReflectColor,\n"
2990 "#endif\n"
2991 "#ifdef USEREFLECTCUBE\n"
2992 "uniform float4x4 ModelToReflectCube,\n"
2993 "uniform sampler2D Texture_ReflectMask,\n"
2994 "uniform samplerCUBE Texture_ReflectCube,\n"
2995 "#endif\n"
2996 "#ifdef MODE_LIGHTDIRECTION\n"
2997 "uniform half3 LightColor,\n"
2998 "#endif\n"
2999 "#ifdef MODE_LIGHTSOURCE\n"
3000 "uniform half3 LightColor,\n"
3001 "#endif\n"
3002 "\n"
3003 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3004 "uniform sampler2D Texture_Attenuation,\n"
3005 "uniform samplerCUBE Texture_Cube,\n"
3006 "#endif\n"
3007 "\n"
3008 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3009 "\n"
3010 "#ifdef USESHADOWMAPRECT\n"
3011 "# ifdef USESHADOWSAMPLER\n"
3012 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3013 "# else\n"
3014 "uniform samplerRECT Texture_ShadowMapRect,\n"
3015 "# endif\n"
3016 "#endif\n"
3017 "\n"
3018 "#ifdef USESHADOWMAP2D\n"
3019 "# ifdef USESHADOWSAMPLER\n"
3020 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3021 "# else\n"
3022 "uniform sampler2D Texture_ShadowMap2D,\n"
3023 "# endif\n"
3024 "#endif\n"
3025 "\n"
3026 "#ifdef USESHADOWMAPVSDCT\n"
3027 "uniform samplerCUBE Texture_CubeProjection,\n"
3028 "#endif\n"
3029 "\n"
3030 "#ifdef USESHADOWMAPCUBE\n"
3031 "# ifdef USESHADOWSAMPLER\n"
3032 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3033 "# else\n"
3034 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3035 "# endif\n"
3036 "#endif\n"
3037 "\n"
3038 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3039 "uniform float2 ShadowMap_TextureScale,\n"
3040 "uniform float4 ShadowMap_Parameters,\n"
3041 "#endif\n"
3042 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3043 "\n"
3044 "out float4 gl_FragColor : COLOR\n"
3045 ")\n"
3046 "{\n"
3047 "       float2 TexCoord = TexCoordBoth.xy;\n"
3048 "#ifdef USEVERTEXTEXTUREBLEND\n"
3049 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3050 "#endif\n"
3051 "#ifdef USEOFFSETMAPPING\n"
3052 "       // apply offsetmapping\n"
3053 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3054 "#define TexCoord TexCoordOffset\n"
3055 "#endif\n"
3056 "\n"
3057 "       // combine the diffuse textures (base, pants, shirt)\n"
3058 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3059 "#ifdef USEALPHAKILL\n"
3060 "       if (color.a < 0.5)\n"
3061 "               discard;\n"
3062 "#endif\n"
3063 "       color.a *= Alpha;\n"
3064 "#ifdef USECOLORMAPPING\n"
3065 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3066 "#endif\n"
3067 "#ifdef USEVERTEXTEXTUREBLEND\n"
3068 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3069 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3070 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3071 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3072 "       color.a = 1.0;\n"
3073 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3074 "#endif\n"
3075 "\n"
3076 "       // get the surface normal\n"
3077 "#ifdef USEVERTEXTEXTUREBLEND\n"
3078 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3079 "#else\n"
3080 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3081 "#endif\n"
3082 "\n"
3083 "       // get the material colors\n"
3084 "       half3 diffusetex = color.rgb;\n"
3085 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3086 "# ifdef USEVERTEXTEXTUREBLEND\n"
3087 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3088 "# else\n"
3089 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3090 "# endif\n"
3091 "#endif\n"
3092 "\n"
3093 "#ifdef USEREFLECTCUBE\n"
3094 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3095 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3096 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3097 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3098 "#endif\n"
3099 "\n"
3100 "\n"
3101 "\n"
3102 "\n"
3103 "#ifdef MODE_LIGHTSOURCE\n"
3104 "       // light source\n"
3105 "#ifdef USEDIFFUSE\n"
3106 "       half3 lightnormal = half3(normalize(LightVector));\n"
3107 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3108 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3109 "#ifdef USESPECULAR\n"
3110 "#ifdef USEEXACTSPECULARMATH\n"
3111 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3112 "#else\n"
3113 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3114 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3115 "#endif\n"
3116 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3117 "#endif\n"
3118 "#else\n"
3119 "       color.rgb = diffusetex * Color_Ambient;\n"
3120 "#endif\n"
3121 "       color.rgb *= LightColor;\n"
3122 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3123 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3124 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3125 "# if defined(USESHADOWMAP2D)\n"
3126 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3127 "# endif\n"
3128 "# if defined(USESHADOWMAPRECT)\n"
3129 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3130 "# endif\n"
3131 "# if defined(USESHADOWMAPCUBE)\n"
3132 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3133 "# endif\n"
3134 "\n"
3135 "#ifdef USESHADOWMAPVSDCT\n"
3136 ", Texture_CubeProjection\n"
3137 "#endif\n"
3138 "       );\n"
3139 "\n"
3140 "#endif\n"
3141 "# ifdef USECUBEFILTER\n"
3142 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3143 "# endif\n"
3144 "#endif // MODE_LIGHTSOURCE\n"
3145 "\n"
3146 "\n"
3147 "\n"
3148 "\n"
3149 "#ifdef MODE_LIGHTDIRECTION\n"
3150 "#define SHADING\n"
3151 "#ifdef USEDIFFUSE\n"
3152 "       half3 lightnormal = half3(normalize(LightVector));\n"
3153 "#endif\n"
3154 "#define lightcolor LightColor\n"
3155 "#endif // MODE_LIGHTDIRECTION\n"
3156 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3157 "#define SHADING\n"
3158 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3159 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3160 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3161 "       // convert modelspace light vector to tangentspace\n"
3162 "       half3 lightnormal;\n"
3163 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3164 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3165 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3166 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3167 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3168 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3169 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3170 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3171 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3172 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3173 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3174 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3175 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3176 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3177 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3178 "#define SHADING\n"
3179 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3180 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3181 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3182 "#endif\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "\n"
3187 "#ifdef MODE_LIGHTMAP\n"
3188 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3189 "#endif // MODE_LIGHTMAP\n"
3190 "#ifdef MODE_VERTEXCOLOR\n"
3191 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3192 "#endif // MODE_VERTEXCOLOR\n"
3193 "#ifdef MODE_FLATCOLOR\n"
3194 "       color.rgb = diffusetex * Color_Ambient;\n"
3195 "#endif // MODE_FLATCOLOR\n"
3196 "\n"
3197 "\n"
3198 "\n"
3199 "\n"
3200 "#ifdef SHADING\n"
3201 "# ifdef USEDIFFUSE\n"
3202 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3203 "#  ifdef USESPECULAR\n"
3204 "#   ifdef USEEXACTSPECULARMATH\n"
3205 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3206 "#   else\n"
3207 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3208 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3209 "#   endif\n"
3210 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3211 "#  else\n"
3212 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3213 "#  endif\n"
3214 "# else\n"
3215 "       color.rgb = diffusetex * Color_Ambient;\n"
3216 "# endif\n"
3217 "#endif\n"
3218 "\n"
3219 "#ifdef USESHADOWMAPORTHO\n"
3220 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3221 "# if defined(USESHADOWMAP2D)\n"
3222 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3223 "# endif\n"
3224 "# if defined(USESHADOWMAPRECT)\n"
3225 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3226 "# endif\n"
3227 "       );\n"
3228 "#endif\n"
3229 "\n"
3230 "#ifdef USEDEFERREDLIGHTMAP\n"
3231 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3232 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3233 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3234 "#endif\n"
3235 "\n"
3236 "#ifdef USEGLOW\n"
3237 "#ifdef USEVERTEXTEXTUREBLEND\n"
3238 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3239 "#else\n"
3240 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3241 "#endif\n"
3242 "#endif\n"
3243 "\n"
3244 "#ifdef USEFOG\n"
3245 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3246 "#endif\n"
3247 "\n"
3248 "       // 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"
3249 "#ifdef USEREFLECTION\n"
3250 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3251 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3252 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3253 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3254 "       // FIXME temporary hack to detect the case that the reflection\n"
3255 "       // gets blackened at edges due to leaving the area that contains actual\n"
3256 "       // content.\n"
3257 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3258 "       // 'appening.\n"
3259 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3260 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3261 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3262 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3263 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3264 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3265 "#endif\n"
3266 "\n"
3267 "       gl_FragColor = float4(color);\n"
3268 "}\n"
3269 "#endif // FRAGMENT_SHADER\n"
3270 "\n"
3271 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3272 "#endif // !MODE_DEFERREDGEOMETRY\n"
3273 "#endif // !MODE_WATER\n"
3274 "#endif // !MODE_REFRACTION\n"
3275 "#endif // !MODE_BLOOMBLUR\n"
3276 "#endif // !MODE_GENERIC\n"
3277 "#endif // !MODE_POSTPROCESS\n"
3278 "#endif // !MODE_SHOWDEPTH\n"
3279 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3280 ;
3281
3282 char *glslshaderstring = NULL;
3283 char *cgshaderstring = NULL;
3284
3285 //=======================================================================================================================================================
3286
3287 typedef struct shaderpermutationinfo_s
3288 {
3289         const char *pretext;
3290         const char *name;
3291 }
3292 shaderpermutationinfo_t;
3293
3294 typedef struct shadermodeinfo_s
3295 {
3296         const char *vertexfilename;
3297         const char *geometryfilename;
3298         const char *fragmentfilename;
3299         const char *pretext;
3300         const char *name;
3301 }
3302 shadermodeinfo_t;
3303
3304 typedef enum shaderpermutation_e
3305 {
3306         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3307         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3308         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3309         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3310         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3311         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3312         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3313         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3314         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3315         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3316         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3317         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3318         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3319         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3320         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3321         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3322         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3323         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3324         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3325         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3326         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3327         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3328         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3329         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3330         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3331         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3332         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3333         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3334         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3335         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3336         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3337 }
3338 shaderpermutation_t;
3339
3340 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3341 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3342 {
3343         {"#define USEDIFFUSE\n", " diffuse"},
3344         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3345         {"#define USEVIEWTINT\n", " viewtint"},
3346         {"#define USECOLORMAPPING\n", " colormapping"},
3347         {"#define USESATURATION\n", " saturation"},
3348         {"#define USEFOGINSIDE\n", " foginside"},
3349         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3350         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3351         {"#define USEGAMMARAMPS\n", " gammaramps"},
3352         {"#define USECUBEFILTER\n", " cubefilter"},
3353         {"#define USEGLOW\n", " glow"},
3354         {"#define USEBLOOM\n", " bloom"},
3355         {"#define USESPECULAR\n", " specular"},
3356         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3357         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3358         {"#define USEREFLECTION\n", " reflection"},
3359         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3360         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3361         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3362         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3363         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3364         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3365         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3366         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3367         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3368         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3369         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3370         {"#define USEALPHAKILL\n", " alphakill"},
3371         {"#define USEREFLECTCUBE\n", " reflectcube"},
3372 };
3373
3374 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3375 typedef enum shadermode_e
3376 {
3377         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3378         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3379         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3380         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3381         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3382         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3383         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3384         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3385         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3386         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3387         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3388         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3389         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3390         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3391         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3392         SHADERMODE_COUNT
3393 }
3394 shadermode_t;
3395
3396 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3397 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3398 {
3399         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3400         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3401         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3402         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3403         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3404         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3405         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3406         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3407         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3408         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3409         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3410         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3411         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3412         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3413         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3414 };
3415
3416 #ifdef SUPPORTCG
3417 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3418 {
3419         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3420         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3421         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3422         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3423         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3424         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3425         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3430         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3431         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435 #endif
3436
3437 struct r_glsl_permutation_s;
3438 typedef struct r_glsl_permutation_s
3439 {
3440         /// hash lookup data
3441         struct r_glsl_permutation_s *hashnext;
3442         unsigned int mode;
3443         unsigned int permutation;
3444
3445         /// indicates if we have tried compiling this permutation already
3446         qboolean compiled;
3447         /// 0 if compilation failed
3448         int program;
3449         /// locations of detected uniforms in program object, or -1 if not found
3450         int loc_Texture_First;
3451         int loc_Texture_Second;
3452         int loc_Texture_GammaRamps;
3453         int loc_Texture_Normal;
3454         int loc_Texture_Color;
3455         int loc_Texture_Gloss;
3456         int loc_Texture_Glow;
3457         int loc_Texture_SecondaryNormal;
3458         int loc_Texture_SecondaryColor;
3459         int loc_Texture_SecondaryGloss;
3460         int loc_Texture_SecondaryGlow;
3461         int loc_Texture_Pants;
3462         int loc_Texture_Shirt;
3463         int loc_Texture_FogHeightTexture;
3464         int loc_Texture_FogMask;
3465         int loc_Texture_Lightmap;
3466         int loc_Texture_Deluxemap;
3467         int loc_Texture_Attenuation;
3468         int loc_Texture_Cube;
3469         int loc_Texture_Refraction;
3470         int loc_Texture_Reflection;
3471         int loc_Texture_ShadowMapRect;
3472         int loc_Texture_ShadowMapCube;
3473         int loc_Texture_ShadowMap2D;
3474         int loc_Texture_CubeProjection;
3475         int loc_Texture_ScreenDepth;
3476         int loc_Texture_ScreenNormalMap;
3477         int loc_Texture_ScreenDiffuse;
3478         int loc_Texture_ScreenSpecular;
3479         int loc_Texture_ReflectMask;
3480         int loc_Texture_ReflectCube;
3481         int loc_Alpha;
3482         int loc_BloomBlur_Parameters;
3483         int loc_ClientTime;
3484         int loc_Color_Ambient;
3485         int loc_Color_Diffuse;
3486         int loc_Color_Specular;
3487         int loc_Color_Glow;
3488         int loc_Color_Pants;
3489         int loc_Color_Shirt;
3490         int loc_DeferredColor_Ambient;
3491         int loc_DeferredColor_Diffuse;
3492         int loc_DeferredColor_Specular;
3493         int loc_DeferredMod_Diffuse;
3494         int loc_DeferredMod_Specular;
3495         int loc_DistortScaleRefractReflect;
3496         int loc_EyePosition;
3497         int loc_FogColor;
3498         int loc_FogHeightFade;
3499         int loc_FogPlane;
3500         int loc_FogPlaneViewDist;
3501         int loc_FogRangeRecip;
3502         int loc_LightColor;
3503         int loc_LightDir;
3504         int loc_LightPosition;
3505         int loc_OffsetMapping_Scale;
3506         int loc_PixelSize;
3507         int loc_ReflectColor;
3508         int loc_ReflectFactor;
3509         int loc_ReflectOffset;
3510         int loc_RefractColor;
3511         int loc_Saturation;
3512         int loc_ScreenCenterRefractReflect;
3513         int loc_ScreenScaleRefractReflect;
3514         int loc_ScreenToDepth;
3515         int loc_ShadowMap_Parameters;
3516         int loc_ShadowMap_TextureScale;
3517         int loc_SpecularPower;
3518         int loc_UserVec1;
3519         int loc_UserVec2;
3520         int loc_UserVec3;
3521         int loc_UserVec4;
3522         int loc_ViewTintColor;
3523         int loc_ViewToLight;
3524         int loc_ModelToLight;
3525         int loc_TexMatrix;
3526         int loc_BackgroundTexMatrix;
3527         int loc_ModelViewProjectionMatrix;
3528         int loc_ModelViewMatrix;
3529         int loc_PixelToScreenTexCoord;
3530         int loc_ModelToReflectCube;
3531         int loc_ShadowMapMatrix;        
3532 }
3533 r_glsl_permutation_t;
3534
3535 #define SHADERPERMUTATION_HASHSIZE 256
3536
3537 /// information about each possible shader permutation
3538 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3539 /// currently selected permutation
3540 r_glsl_permutation_t *r_glsl_permutation;
3541 /// storage for permutations linked in the hash table
3542 memexpandablearray_t r_glsl_permutationarray;
3543
3544 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3545 {
3546         //unsigned int hashdepth = 0;
3547         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3548         r_glsl_permutation_t *p;
3549         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3550         {
3551                 if (p->mode == mode && p->permutation == permutation)
3552                 {
3553                         //if (hashdepth > 10)
3554                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3555                         return p;
3556                 }
3557                 //hashdepth++;
3558         }
3559         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3560         p->mode = mode;
3561         p->permutation = permutation;
3562         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3563         r_glsl_permutationhash[mode][hashindex] = p;
3564         //if (hashdepth > 10)
3565         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3566         return p;
3567 }
3568
3569 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3570 {
3571         char *shaderstring;
3572         if (!filename || !filename[0])
3573                 return NULL;
3574         if (!strcmp(filename, "glsl/default.glsl"))
3575         {
3576                 if (!glslshaderstring)
3577                 {
3578                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3579                         if (glslshaderstring)
3580                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3581                         else
3582                                 glslshaderstring = (char *)builtinshaderstring;
3583                 }
3584                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3585                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3586                 return shaderstring;
3587         }
3588         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3589         if (shaderstring)
3590         {
3591                 if (printfromdisknotice)
3592                         Con_DPrintf("from disk %s... ", filename);
3593                 return shaderstring;
3594         }
3595         return shaderstring;
3596 }
3597
3598 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3599 {
3600         int i;
3601         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3602         int vertstrings_count = 0;
3603         int geomstrings_count = 0;
3604         int fragstrings_count = 0;
3605         char *vertexstring, *geometrystring, *fragmentstring;
3606         const char *vertstrings_list[32+3];
3607         const char *geomstrings_list[32+3];
3608         const char *fragstrings_list[32+3];
3609         char permutationname[256];
3610
3611         if (p->compiled)
3612                 return;
3613         p->compiled = true;
3614         p->program = 0;
3615
3616         permutationname[0] = 0;
3617         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3618         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3619         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3620
3621         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3622
3623         // the first pretext is which type of shader to compile as
3624         // (later these will all be bound together as a program object)
3625         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3626         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3627         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3628
3629         // the second pretext is the mode (for example a light source)
3630         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3631         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3632         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3633         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3634
3635         // now add all the permutation pretexts
3636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3637         {
3638                 if (permutation & (1<<i))
3639                 {
3640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3644                 }
3645                 else
3646                 {
3647                         // keep line numbers correct
3648                         vertstrings_list[vertstrings_count++] = "\n";
3649                         geomstrings_list[geomstrings_count++] = "\n";
3650                         fragstrings_list[fragstrings_count++] = "\n";
3651                 }
3652         }
3653
3654         // now append the shader text itself
3655         vertstrings_list[vertstrings_count++] = vertexstring;
3656         geomstrings_list[geomstrings_count++] = geometrystring;
3657         fragstrings_list[fragstrings_count++] = fragmentstring;
3658
3659         // if any sources were NULL, clear the respective list
3660         if (!vertexstring)
3661                 vertstrings_count = 0;
3662         if (!geometrystring)
3663                 geomstrings_count = 0;
3664         if (!fragmentstring)
3665                 fragstrings_count = 0;
3666
3667         // compile the shader program
3668         if (vertstrings_count + geomstrings_count + fragstrings_count)
3669                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3670         if (p->program)
3671         {
3672                 CHECKGLERROR
3673                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3674                 // look up all the uniform variable names we care about, so we don't
3675                 // have to look them up every time we set them
3676
3677                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3678                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3679                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3680                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3681                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3682                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3683                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3684                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3685                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3686                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3687                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3688                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3689                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3690                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3691                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3692                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3693                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3694                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3695                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3696                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3697                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3698                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3699                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3700                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3701                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3702                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3703                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3704                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3705                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3706                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3707                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3708                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3709                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3710                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3711                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3712                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3713                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3714                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3715                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3716                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3717                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3718                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3719                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3720                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3721                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3722                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3723                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3724                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3725                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3726                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3727                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3728                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3729                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3730                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3731                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3732                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3733                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3734                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3735                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3736                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3737                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3738                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3739                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3740                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3741                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3742                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3743                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3744                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3745                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3746                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3747                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3748                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3749                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3750                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3751                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3752                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3753                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3754                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3755                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3756                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3757                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3758                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3759                 // initialize the samplers to refer to the texture units we use
3760                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3761                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3762                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3763                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3764                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3765                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3766                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3767                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3768                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3769                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3770                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3771                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3772                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3773                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3774                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3775                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3776                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3777                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3778                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3779                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3780                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3781                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3782                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3783                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3784                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3785                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3786                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3787                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3788                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3789                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3790                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3791                 CHECKGLERROR
3792                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3793         }
3794         else
3795                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3796
3797         // free the strings
3798         if (vertexstring)
3799                 Mem_Free(vertexstring);
3800         if (geometrystring)
3801                 Mem_Free(geometrystring);
3802         if (fragmentstring)
3803                 Mem_Free(fragmentstring);
3804 }
3805
3806 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3807 {
3808         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3809         if (r_glsl_permutation != perm)
3810         {
3811                 r_glsl_permutation = perm;
3812                 if (!r_glsl_permutation->program)
3813                 {
3814                         if (!r_glsl_permutation->compiled)
3815                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3816                         if (!r_glsl_permutation->program)
3817                         {
3818                                 // remove features until we find a valid permutation
3819                                 int i;
3820                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3821                                 {
3822                                         // reduce i more quickly whenever it would not remove any bits
3823                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3824                                         if (!(permutation & j))
3825                                                 continue;
3826                                         permutation -= j;
3827                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3828                                         if (!r_glsl_permutation->compiled)
3829                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3830                                         if (r_glsl_permutation->program)
3831                                                 break;
3832                                 }
3833                                 if (i >= SHADERPERMUTATION_COUNT)
3834                                 {
3835                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3836                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3837                                         qglUseProgramObjectARB(0);CHECKGLERROR
3838                                         return; // no bit left to clear, entire mode is broken
3839                                 }
3840                         }
3841                 }
3842                 CHECKGLERROR
3843                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3844         }
3845         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3846         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3847         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3848 }
3849
3850 #ifdef SUPPORTCG
3851 #include <Cg/cgGL.h>
3852 struct r_cg_permutation_s;
3853 typedef struct r_cg_permutation_s
3854 {
3855         /// hash lookup data
3856         struct r_cg_permutation_s *hashnext;
3857         unsigned int mode;
3858         unsigned int permutation;
3859
3860         /// indicates if we have tried compiling this permutation already
3861         qboolean compiled;
3862         /// 0 if compilation failed
3863         CGprogram vprogram;
3864         CGprogram fprogram;
3865         /// locations of detected parameters in programs, or NULL if not found
3866         CGparameter vp_EyePosition;
3867         CGparameter vp_FogPlane;
3868         CGparameter vp_LightDir;
3869         CGparameter vp_LightPosition;
3870         CGparameter vp_ModelToLight;
3871         CGparameter vp_TexMatrix;
3872         CGparameter vp_BackgroundTexMatrix;
3873         CGparameter vp_ModelViewProjectionMatrix;
3874         CGparameter vp_ModelViewMatrix;
3875         CGparameter vp_ShadowMapMatrix;
3876
3877         CGparameter fp_Texture_First;
3878         CGparameter fp_Texture_Second;
3879         CGparameter fp_Texture_GammaRamps;
3880         CGparameter fp_Texture_Normal;
3881         CGparameter fp_Texture_Color;
3882         CGparameter fp_Texture_Gloss;
3883         CGparameter fp_Texture_Glow;
3884         CGparameter fp_Texture_SecondaryNormal;
3885         CGparameter fp_Texture_SecondaryColor;
3886         CGparameter fp_Texture_SecondaryGloss;
3887         CGparameter fp_Texture_SecondaryGlow;
3888         CGparameter fp_Texture_Pants;
3889         CGparameter fp_Texture_Shirt;
3890         CGparameter fp_Texture_FogHeightTexture;
3891         CGparameter fp_Texture_FogMask;
3892         CGparameter fp_Texture_Lightmap;
3893         CGparameter fp_Texture_Deluxemap;
3894         CGparameter fp_Texture_Attenuation;
3895         CGparameter fp_Texture_Cube;
3896         CGparameter fp_Texture_Refraction;
3897         CGparameter fp_Texture_Reflection;
3898         CGparameter fp_Texture_ShadowMapRect;
3899         CGparameter fp_Texture_ShadowMapCube;
3900         CGparameter fp_Texture_ShadowMap2D;
3901         CGparameter fp_Texture_CubeProjection;
3902         CGparameter fp_Texture_ScreenDepth;
3903         CGparameter fp_Texture_ScreenNormalMap;
3904         CGparameter fp_Texture_ScreenDiffuse;
3905         CGparameter fp_Texture_ScreenSpecular;
3906         CGparameter fp_Texture_ReflectMask;
3907         CGparameter fp_Texture_ReflectCube;
3908         CGparameter fp_Alpha;
3909         CGparameter fp_BloomBlur_Parameters;
3910         CGparameter fp_ClientTime;
3911         CGparameter fp_Color_Ambient;
3912         CGparameter fp_Color_Diffuse;
3913         CGparameter fp_Color_Specular;
3914         CGparameter fp_Color_Glow;
3915         CGparameter fp_Color_Pants;
3916         CGparameter fp_Color_Shirt;
3917         CGparameter fp_DeferredColor_Ambient;
3918         CGparameter fp_DeferredColor_Diffuse;
3919         CGparameter fp_DeferredColor_Specular;
3920         CGparameter fp_DeferredMod_Diffuse;
3921         CGparameter fp_DeferredMod_Specular;
3922         CGparameter fp_DistortScaleRefractReflect;
3923         CGparameter fp_EyePosition;
3924         CGparameter fp_FogColor;
3925         CGparameter fp_FogHeightFade;
3926         CGparameter fp_FogPlane;
3927         CGparameter fp_FogPlaneViewDist;
3928         CGparameter fp_FogRangeRecip;
3929         CGparameter fp_LightColor;
3930         CGparameter fp_LightDir;
3931         CGparameter fp_LightPosition;
3932         CGparameter fp_OffsetMapping_Scale;
3933         CGparameter fp_PixelSize;
3934         CGparameter fp_ReflectColor;
3935         CGparameter fp_ReflectFactor;
3936         CGparameter fp_ReflectOffset;
3937         CGparameter fp_RefractColor;
3938         CGparameter fp_Saturation;
3939         CGparameter fp_ScreenCenterRefractReflect;
3940         CGparameter fp_ScreenScaleRefractReflect;
3941         CGparameter fp_ScreenToDepth;
3942         CGparameter fp_ShadowMap_Parameters;
3943         CGparameter fp_ShadowMap_TextureScale;
3944         CGparameter fp_SpecularPower;
3945         CGparameter fp_UserVec1;
3946         CGparameter fp_UserVec2;
3947         CGparameter fp_UserVec3;
3948         CGparameter fp_UserVec4;
3949         CGparameter fp_ViewTintColor;
3950         CGparameter fp_ViewToLight;
3951         CGparameter fp_PixelToScreenTexCoord;
3952         CGparameter fp_ModelToReflectCube;
3953 }
3954 r_cg_permutation_t;
3955
3956 /// information about each possible shader permutation
3957 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3958 /// currently selected permutation
3959 r_cg_permutation_t *r_cg_permutation;
3960 /// storage for permutations linked in the hash table
3961 memexpandablearray_t r_cg_permutationarray;
3962
3963 #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));}}
3964
3965 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3966 {
3967         //unsigned int hashdepth = 0;
3968         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3969         r_cg_permutation_t *p;
3970         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3971         {
3972                 if (p->mode == mode && p->permutation == permutation)
3973                 {
3974                         //if (hashdepth > 10)
3975                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3976                         return p;
3977                 }
3978                 //hashdepth++;
3979         }
3980         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3981         p->mode = mode;
3982         p->permutation = permutation;
3983         p->hashnext = r_cg_permutationhash[mode][hashindex];
3984         r_cg_permutationhash[mode][hashindex] = p;
3985         //if (hashdepth > 10)
3986         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3987         return p;
3988 }
3989
3990 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3991 {
3992         char *shaderstring;
3993         if (!filename || !filename[0])
3994                 return NULL;
3995         if (!strcmp(filename, "cg/default.cg"))
3996         {
3997                 if (!cgshaderstring)
3998                 {
3999                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4000                         if (cgshaderstring)
4001                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4002                         else
4003                                 cgshaderstring = (char *)builtincgshaderstring;
4004                 }
4005                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4006                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4007                 return shaderstring;
4008         }
4009         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4010         if (shaderstring)
4011         {
4012                 if (printfromdisknotice)
4013                         Con_DPrintf("from disk %s... ", filename);
4014                 return shaderstring;
4015         }
4016         return shaderstring;
4017 }
4018
4019 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4020 {
4021         // TODO: load or create .fp and .vp shader files
4022 }
4023
4024 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4025 {
4026         int i;
4027         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4028         int vertstrings_count = 0, vertstring_length = 0;
4029         int geomstrings_count = 0, geomstring_length = 0;
4030         int fragstrings_count = 0, fragstring_length = 0;
4031         char *t;
4032         char *vertexstring, *geometrystring, *fragmentstring;
4033         char *vertstring, *geomstring, *fragstring;
4034         const char *vertstrings_list[32+3];
4035         const char *geomstrings_list[32+3];
4036         const char *fragstrings_list[32+3];
4037         char permutationname[256];
4038         char cachename[256];
4039         CGprofile vertexProfile;
4040         CGprofile fragmentProfile;
4041
4042         if (p->compiled)
4043                 return;
4044         p->compiled = true;
4045         p->vprogram = NULL;
4046         p->fprogram = NULL;
4047
4048         permutationname[0] = 0;
4049         cachename[0] = 0;
4050         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4051         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4052         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4053
4054         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4055         strlcat(cachename, "cg/", sizeof(cachename));
4056
4057         // the first pretext is which type of shader to compile as
4058         // (later these will all be bound together as a program object)
4059         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4060         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4061         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4062
4063         // the second pretext is the mode (for example a light source)
4064         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4065         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4066         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4067         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4068         strlcat(cachename, modeinfo->name, sizeof(cachename));
4069
4070         // now add all the permutation pretexts
4071         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4072         {
4073                 if (permutation & (1<<i))
4074                 {
4075                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4076                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4077                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4078                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4079                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4080                 }
4081                 else
4082                 {
4083                         // keep line numbers correct
4084                         vertstrings_list[vertstrings_count++] = "\n";
4085                         geomstrings_list[geomstrings_count++] = "\n";
4086                         fragstrings_list[fragstrings_count++] = "\n";
4087                 }
4088         }
4089
4090         // replace spaces in the cachename with _ characters
4091         for (i = 0;cachename[i];i++)
4092                 if (cachename[i] == ' ')
4093                         cachename[i] = '_';
4094
4095         // now append the shader text itself
4096         vertstrings_list[vertstrings_count++] = vertexstring;
4097         geomstrings_list[geomstrings_count++] = geometrystring;
4098         fragstrings_list[fragstrings_count++] = fragmentstring;
4099
4100         // if any sources were NULL, clear the respective list
4101         if (!vertexstring)
4102                 vertstrings_count = 0;
4103         if (!geometrystring)
4104                 geomstrings_count = 0;
4105         if (!fragmentstring)
4106                 fragstrings_count = 0;
4107
4108         vertstring_length = 0;
4109         for (i = 0;i < vertstrings_count;i++)
4110                 vertstring_length += strlen(vertstrings_list[i]);
4111         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4112         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4113                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4114
4115         geomstring_length = 0;
4116         for (i = 0;i < geomstrings_count;i++)
4117                 geomstring_length += strlen(geomstrings_list[i]);
4118         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4119         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4120                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4121
4122         fragstring_length = 0;
4123         for (i = 0;i < fragstrings_count;i++)
4124                 fragstring_length += strlen(fragstrings_list[i]);
4125         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4126         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4127                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4128
4129         CHECKGLERROR
4130         CHECKCGERROR
4131         //vertexProfile = CG_PROFILE_ARBVP1;
4132         //fragmentProfile = CG_PROFILE_ARBFP1;
4133         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4134         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4135         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4136         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4137         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4138         CHECKGLERROR
4139
4140         // try to load the cached shader, or generate one
4141         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4142
4143         // if caching failed, do a dynamic compile for now
4144         CHECKCGERROR
4145         if (vertstring[0] && !p->vprogram)
4146                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4147         CHECKCGERROR
4148         if (fragstring[0] && !p->fprogram)
4149                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4150         CHECKCGERROR
4151
4152         // look up all the uniform variable names we care about, so we don't
4153         // have to look them up every time we set them
4154         if (p->vprogram)
4155         {
4156                 CHECKCGERROR
4157                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4158                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4159                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4160                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4161                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4162                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4163                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4164                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4165                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4166                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4167                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4168                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4169                 CHECKCGERROR
4170         }
4171         if (p->fprogram)
4172         {
4173                 CHECKCGERROR
4174                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4175                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4176                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4177                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4178                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4179                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4180                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4181                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4182                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4183                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4184                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4185                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4186                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4187                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4188                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4189                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4190                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4191                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4192                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4193                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4194                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4195                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4196                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4197                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4198                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4199                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4200                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4201                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4202                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4203                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4204                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4205                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4206                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4207                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4208                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4209                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4210                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4211                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4212                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4213                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4214                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4215                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4216                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4217                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4218                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4219                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4220                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4221                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4222                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4223                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4224                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4225                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4226                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4227                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4228                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4229                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4230                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4231                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4232                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4233                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4234                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4235                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4236                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4237                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4238                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4239                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4240                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4241                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4242                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4243                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4244                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4245                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4246                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4247                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4248                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4249                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4250                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4251                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4252                 CHECKCGERROR
4253         }
4254
4255         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4256                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4257         else
4258                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4259
4260         // free the strings
4261         if (vertstring)
4262                 Mem_Free(vertstring);
4263         if (geomstring)
4264                 Mem_Free(geomstring);
4265         if (fragstring)
4266                 Mem_Free(fragstring);
4267         if (vertexstring)
4268                 Mem_Free(vertexstring);
4269         if (geometrystring)
4270                 Mem_Free(geometrystring);
4271         if (fragmentstring)
4272                 Mem_Free(fragmentstring);
4273 }
4274
4275 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4276 {
4277         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4278         CHECKGLERROR
4279         CHECKCGERROR
4280         if (r_cg_permutation != perm)
4281         {
4282                 r_cg_permutation = perm;
4283                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4284                 {
4285                         if (!r_cg_permutation->compiled)
4286                                 R_CG_CompilePermutation(perm, mode, permutation);
4287                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4288                         {
4289                                 // remove features until we find a valid permutation
4290                                 int i;
4291                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4292                                 {
4293                                         // reduce i more quickly whenever it would not remove any bits
4294                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4295                                         if (!(permutation & j))
4296                                                 continue;
4297                                         permutation -= j;
4298                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4299                                         if (!r_cg_permutation->compiled)
4300                                                 R_CG_CompilePermutation(perm, mode, permutation);
4301                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4302                                                 break;
4303                                 }
4304                                 if (i >= SHADERPERMUTATION_COUNT)
4305                                 {
4306                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4307                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4308                                         return; // no bit left to clear, entire mode is broken
4309                                 }
4310                         }
4311                 }
4312                 CHECKGLERROR
4313                 CHECKCGERROR
4314                 if (r_cg_permutation->vprogram)
4315                 {
4316                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4317                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4318                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4319                 }
4320                 else
4321                 {
4322                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4323                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4324                 }
4325                 if (r_cg_permutation->fprogram)
4326                 {
4327                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4328                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4329                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4330                 }
4331                 else
4332                 {
4333                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4334                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4335                 }
4336         }
4337         CHECKCGERROR
4338         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4339         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4340         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4341 }
4342
4343 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4344 {
4345         cgGLSetTextureParameter(param, R_GetTexture(tex));
4346         cgGLEnableTextureParameter(param);
4347 }
4348 #endif
4349
4350 void R_GLSL_Restart_f(void)
4351 {
4352         unsigned int i, limit;
4353         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4354                 Mem_Free(glslshaderstring);
4355         glslshaderstring = NULL;
4356         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4357                 Mem_Free(cgshaderstring);
4358         cgshaderstring = NULL;
4359         switch(vid.renderpath)
4360         {
4361         case RENDERPATH_GL20:
4362                 {
4363                         r_glsl_permutation_t *p;
4364                         r_glsl_permutation = NULL;
4365                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4366                         for (i = 0;i < limit;i++)
4367                         {
4368                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4369                                 {
4370                                         GL_Backend_FreeProgram(p->program);
4371                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4372                                 }
4373                         }
4374                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4375                 }
4376                 break;
4377         case RENDERPATH_CGGL:
4378 #ifdef SUPPORTCG
4379                 {
4380                         r_cg_permutation_t *p;
4381                         r_cg_permutation = NULL;
4382                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4383                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4384                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4385                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4386                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4387                         for (i = 0;i < limit;i++)
4388                         {
4389                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4390                                 {
4391                                         if (p->vprogram)
4392                                                 cgDestroyProgram(p->vprogram);
4393                                         if (p->fprogram)
4394                                                 cgDestroyProgram(p->fprogram);
4395                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4396                                 }
4397                         }
4398                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4399                 }
4400                 break;
4401 #endif
4402         case RENDERPATH_GL13:
4403         case RENDERPATH_GL11:
4404                 break;
4405         }
4406 }
4407
4408 void R_GLSL_DumpShader_f(void)
4409 {
4410         int i;
4411         qfile_t *file;
4412
4413         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4414         if (file)
4415         {
4416                 FS_Print(file, "/* The engine may define the following macros:\n");
4417                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4418                 for (i = 0;i < SHADERMODE_COUNT;i++)
4419                         FS_Print(file, glslshadermodeinfo[i].pretext);
4420                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4421                         FS_Print(file, shaderpermutationinfo[i].pretext);
4422                 FS_Print(file, "*/\n");
4423                 FS_Print(file, builtinshaderstring);
4424                 FS_Close(file);
4425                 Con_Printf("glsl/default.glsl written\n");
4426         }
4427         else
4428                 Con_Printf("failed to write to glsl/default.glsl\n");
4429
4430 #ifdef SUPPORTCG
4431         file = FS_OpenRealFile("cg/default.cg", "w", false);
4432         if (file)
4433         {
4434                 FS_Print(file, "/* The engine may define the following macros:\n");
4435                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4436                 for (i = 0;i < SHADERMODE_COUNT;i++)
4437                         FS_Print(file, cgshadermodeinfo[i].pretext);
4438                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4439                         FS_Print(file, shaderpermutationinfo[i].pretext);
4440                 FS_Print(file, "*/\n");
4441                 FS_Print(file, builtincgshaderstring);
4442                 FS_Close(file);
4443                 Con_Printf("cg/default.cg written\n");
4444         }
4445         else
4446                 Con_Printf("failed to write to cg/default.cg\n");
4447 #endif
4448 }
4449
4450 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4451 {
4452         if (!second)
4453                 texturemode = GL_MODULATE;
4454         switch (vid.renderpath)
4455         {
4456         case RENDERPATH_GL20:
4457                 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))));
4458                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4459                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4460                 break;
4461         case RENDERPATH_CGGL:
4462 #ifdef SUPPORTCG
4463                 CHECKCGERROR
4464                 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))));
4465                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4466                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4467 #endif
4468                 break;
4469         case RENDERPATH_GL13:
4470                 R_Mesh_TexBind(0, first );
4471                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4472                 R_Mesh_TexBind(1, second);
4473                 if (second)
4474                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4475                 break;
4476         case RENDERPATH_GL11:
4477                 R_Mesh_TexBind(0, first );
4478                 break;
4479         }
4480 }
4481
4482 void R_SetupShader_DepthOrShadow(void)
4483 {
4484         switch (vid.renderpath)
4485         {
4486         case RENDERPATH_GL20:
4487                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4488                 break;
4489         case RENDERPATH_CGGL:
4490 #ifdef SUPPORTCG
4491                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4492 #endif
4493                 break;
4494         case RENDERPATH_GL13:
4495                 R_Mesh_TexBind(0, 0);
4496                 R_Mesh_TexBind(1, 0);
4497                 break;
4498         case RENDERPATH_GL11:
4499                 R_Mesh_TexBind(0, 0);
4500                 break;
4501         }
4502 }
4503
4504 void R_SetupShader_ShowDepth(void)
4505 {
4506         switch (vid.renderpath)
4507         {
4508         case RENDERPATH_GL20:
4509                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4510                 break;
4511         case RENDERPATH_CGGL:
4512 #ifdef SUPPORTCG
4513                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4514 #endif
4515                 break;
4516         case RENDERPATH_GL13:
4517                 break;
4518         case RENDERPATH_GL11:
4519                 break;
4520         }
4521 }
4522
4523 extern qboolean r_shadow_usingdeferredprepass;
4524 extern cvar_t r_shadow_deferred_8bitrange;
4525 extern rtexture_t *r_shadow_attenuationgradienttexture;
4526 extern rtexture_t *r_shadow_attenuation2dtexture;
4527 extern rtexture_t *r_shadow_attenuation3dtexture;
4528 extern qboolean r_shadow_usingshadowmaprect;
4529 extern qboolean r_shadow_usingshadowmapcube;
4530 extern qboolean r_shadow_usingshadowmap2d;
4531 extern qboolean r_shadow_usingshadowmaportho;
4532 extern float r_shadow_shadowmap_texturescale[2];
4533 extern float r_shadow_shadowmap_parameters[4];
4534 extern qboolean r_shadow_shadowmapvsdct;
4535 extern qboolean r_shadow_shadowmapsampler;
4536 extern int r_shadow_shadowmappcf;
4537 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4538 extern rtexture_t *r_shadow_shadowmap2dtexture;
4539 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4540 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4541 extern matrix4x4_t r_shadow_shadowmapmatrix;
4542 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4543 extern int r_shadow_prepass_width;
4544 extern int r_shadow_prepass_height;
4545 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4546 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4547 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4548 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4549 extern cvar_t gl_mesh_separatearrays;
4550 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist)
4551 {
4552         // select a permutation of the lighting shader appropriate to this
4553         // combination of texture, entity, light source, and fogging, only use the
4554         // minimum features necessary to avoid wasting rendering time in the
4555         // fragment shader on features that are not being used
4556         unsigned int permutation = 0;
4557         unsigned int mode = 0;
4558         float m16f[16];
4559         if (rsurfacepass == RSURFPASS_BACKGROUND)
4560         {
4561                 // distorted background
4562                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4563                         mode = SHADERMODE_WATER;
4564                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4565                         mode = SHADERMODE_REFRACTION;
4566                 else
4567                 {
4568                         mode = SHADERMODE_GENERIC;
4569                         permutation |= SHADERPERMUTATION_DIFFUSE;
4570                 }
4571                 GL_AlphaTest(false);
4572                 GL_BlendFunc(GL_ONE, GL_ZERO);
4573         }
4574         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4575         {
4576                 if (r_glsl_offsetmapping.integer)
4577                 {
4578                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4579                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4580                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4581                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4582                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4583                         {
4584                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4585                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4586                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4587                         }
4588                 }
4589                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4590                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4591                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4592                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4593                 // normalmap (deferred prepass), may use alpha test on diffuse
4594                 mode = SHADERMODE_DEFERREDGEOMETRY;
4595                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4596                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4597                 GL_AlphaTest(false);
4598                 GL_BlendFunc(GL_ONE, GL_ZERO);
4599         }
4600         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4601         {
4602                 if (r_glsl_offsetmapping.integer)
4603                 {
4604                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4605                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4606                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4607                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4608                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4609                         {
4610                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4611                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4612                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4613                         }
4614                 }
4615                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4616                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4617                 // light source
4618                 mode = SHADERMODE_LIGHTSOURCE;
4619                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4620                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4621                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4622                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4623                 if (diffusescale > 0)
4624                         permutation |= SHADERPERMUTATION_DIFFUSE;
4625                 if (specularscale > 0)
4626                 {
4627                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4628                         if (r_shadow_glossexact.integer)
4629                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4630                 }
4631                 if (r_refdef.fogenabled)
4632                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4633                 if (rsurface.texture->colormapping)
4634                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4635                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4636                 {
4637                         if (r_shadow_usingshadowmaprect)
4638                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4639                         if (r_shadow_usingshadowmap2d)
4640                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4641                         if (r_shadow_usingshadowmapcube)
4642                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4643                         else if(r_shadow_shadowmapvsdct)
4644                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4645
4646                         if (r_shadow_shadowmapsampler)
4647                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4648                         if (r_shadow_shadowmappcf > 1)
4649                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4650                         else if (r_shadow_shadowmappcf)
4651                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4652                 }
4653                 if (rsurface.texture->reflectmasktexture)
4654                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4655                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4656                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4657         }
4658         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4659         {
4660                 if (r_glsl_offsetmapping.integer)
4661                 {
4662                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4663                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4664                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4665                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4666                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4667                         {
4668                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4669                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4670                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4671                         }
4672                 }
4673                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4674                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4675                 // unshaded geometry (fullbright or ambient model lighting)
4676                 mode = SHADERMODE_FLATCOLOR;
4677                 ambientscale = diffusescale = specularscale = 0;
4678                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4679                         permutation |= SHADERPERMUTATION_GLOW;
4680                 if (r_refdef.fogenabled)
4681                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4682                 if (rsurface.texture->colormapping)
4683                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4684                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4685                 {
4686                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4687                         if (r_shadow_usingshadowmaprect)
4688                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4689                         if (r_shadow_usingshadowmap2d)
4690                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4691
4692                         if (r_shadow_shadowmapsampler)
4693                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4694                         if (r_shadow_shadowmappcf > 1)
4695                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4696                         else if (r_shadow_shadowmappcf)
4697                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4698                 }
4699                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4700                         permutation |= SHADERPERMUTATION_REFLECTION;
4701                 if (rsurface.texture->reflectmasktexture)
4702                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4703                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4704                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4705         }
4706         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4707         {
4708                 if (r_glsl_offsetmapping.integer)
4709                 {
4710                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4711                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4712                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4713                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4714                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4715                         {
4716                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4717                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4718                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4719                         }
4720                 }
4721                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4722                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4723                 // directional model lighting
4724                 mode = SHADERMODE_LIGHTDIRECTION;
4725                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4726                         permutation |= SHADERPERMUTATION_GLOW;
4727                 permutation |= SHADERPERMUTATION_DIFFUSE;
4728                 if (specularscale > 0)
4729                 {
4730                         permutation |= SHADERPERMUTATION_SPECULAR;
4731                         if (r_shadow_glossexact.integer)
4732                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4733                 }
4734                 if (r_refdef.fogenabled)
4735                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4736                 if (rsurface.texture->colormapping)
4737                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4738                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4739                 {
4740                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4741                         if (r_shadow_usingshadowmaprect)
4742                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4743                         if (r_shadow_usingshadowmap2d)
4744                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4745
4746                         if (r_shadow_shadowmapsampler)
4747                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4748                         if (r_shadow_shadowmappcf > 1)
4749                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4750                         else if (r_shadow_shadowmappcf)
4751                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4752                 }
4753                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4754                         permutation |= SHADERPERMUTATION_REFLECTION;
4755                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4756                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4757                 if (rsurface.texture->reflectmasktexture)
4758                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4759                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4760                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4761         }
4762         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4763         {
4764                 if (r_glsl_offsetmapping.integer)
4765                 {
4766                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4767                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4768                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4769                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4770                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4771                         {
4772                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4773                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4774                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4775                         }
4776                 }
4777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4778                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4779                 // ambient model lighting
4780                 mode = SHADERMODE_LIGHTDIRECTION;
4781                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4782                         permutation |= SHADERPERMUTATION_GLOW;
4783                 if (r_refdef.fogenabled)
4784                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4785                 if (rsurface.texture->colormapping)
4786                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4787                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4788                 {
4789                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4790                         if (r_shadow_usingshadowmaprect)
4791                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4792                         if (r_shadow_usingshadowmap2d)
4793                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4794
4795                         if (r_shadow_shadowmapsampler)
4796                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4797                         if (r_shadow_shadowmappcf > 1)
4798                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4799                         else if (r_shadow_shadowmappcf)
4800                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4801                 }
4802                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4803                         permutation |= SHADERPERMUTATION_REFLECTION;
4804                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4805                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4806                 if (rsurface.texture->reflectmasktexture)
4807                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4808                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4809                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4810         }
4811         else
4812         {
4813                 if (r_glsl_offsetmapping.integer)
4814                 {
4815                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4816                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4817                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4818                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4819                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4820                         {
4821                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4822                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4823                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4824                         }
4825                 }
4826                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4827                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4828                 // lightmapped wall
4829                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4830                         permutation |= SHADERPERMUTATION_GLOW;
4831                 if (r_refdef.fogenabled)
4832                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4833                 if (rsurface.texture->colormapping)
4834                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4835                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4836                 {
4837                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4838                         if (r_shadow_usingshadowmaprect)
4839                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4840                         if (r_shadow_usingshadowmap2d)
4841                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4842
4843                         if (r_shadow_shadowmapsampler)
4844                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4845                         if (r_shadow_shadowmappcf > 1)
4846                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4847                         else if (r_shadow_shadowmappcf)
4848                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4849                 }
4850                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4851                         permutation |= SHADERPERMUTATION_REFLECTION;
4852                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4853                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4854                 if (rsurface.texture->reflectmasktexture)
4855                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4856                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4857                 {
4858                         // deluxemapping (light direction texture)
4859                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4860                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4861                         else
4862                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4863                         permutation |= SHADERPERMUTATION_DIFFUSE;
4864                         if (specularscale > 0)
4865                         {
4866                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4867                                 if (r_shadow_glossexact.integer)
4868                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4869                         }
4870                 }
4871                 else if (r_glsl_deluxemapping.integer >= 2)
4872                 {
4873                         // fake deluxemapping (uniform light direction in tangentspace)
4874                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4875                         permutation |= SHADERPERMUTATION_DIFFUSE;
4876                         if (specularscale > 0)
4877                         {
4878                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4879                                 if (r_shadow_glossexact.integer)
4880                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4881                         }
4882                 }
4883                 else if (rsurface.uselightmaptexture)
4884                 {
4885                         // ordinary lightmapping (q1bsp, q3bsp)
4886                         mode = SHADERMODE_LIGHTMAP;
4887                 }
4888                 else
4889                 {
4890                         // ordinary vertex coloring (q3bsp)
4891                         mode = SHADERMODE_VERTEXCOLOR;
4892                 }
4893                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4894                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4895         }
4896         switch(vid.renderpath)
4897         {
4898         case RENDERPATH_GL20:
4899                 if (gl_mesh_separatearrays.integer)
4900                 {
4901                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4902                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4903                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
4904                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
4905                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
4906                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
4907                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
4908                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
4909                 }
4910                 else
4911                 {
4912                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4913                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
4914                 }
4915                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4916                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4917                 if (mode == SHADERMODE_LIGHTSOURCE)
4918                 {
4919                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4920                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4921                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4922                         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);
4923                         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);
4924                         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);
4925         
4926                         // additive passes are only darkened by fog, not tinted
4927                         if (r_glsl_permutation->loc_FogColor >= 0)
4928                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4929                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4930                 }
4931                 else
4932                 {
4933                         if (mode == SHADERMODE_FLATCOLOR)
4934                         {
4935                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4936                         }
4937                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4938                         {
4939                                 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]);
4940                                 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]);
4941                                 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);
4942                                 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);
4943                                 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);
4944                                 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]);
4945                                 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]);
4946                         }
4947                         else
4948                         {
4949                                 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]);
4950                                 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]);
4951                                 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);
4952                                 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);
4953                                 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);
4954                         }
4955                         // additive passes are only darkened by fog, not tinted
4956                         if (r_glsl_permutation->loc_FogColor >= 0)
4957                         {
4958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4959                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4960                                 else
4961                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4962                         }
4963                         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);
4964                         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]);
4965                         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]);
4966                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4967                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
4968                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
4969                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
4970                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4971                 }
4972                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
4973                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
4974                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
4975                 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]);
4976                 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]);
4977
4978                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
4979                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
4980                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
4981                 if (r_glsl_permutation->loc_Color_Pants >= 0)
4982                 {
4983                         if (rsurface.texture->pantstexture)
4984                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
4985                         else
4986                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
4987                 }
4988                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
4989                 {
4990                         if (rsurface.texture->shirttexture)
4991                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
4992                         else
4993                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
4994                 }
4995                 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]);
4996                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
4997                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
4998                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
4999                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5000                 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]);
5001                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5002
5003         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5004         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5005         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5006                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5007                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5008                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5009                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5010                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5011                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5012                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5013                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5014                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5015                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5016                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5017                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5018                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5019                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5020                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5021                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_blanknormalmap                            );
5022                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5023                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5024                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5025                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5026                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5027                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5028                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5029                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5030                 {
5031                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5032                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5033                         if (rsurface.rtlight)
5034                         {
5035                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5036                                 if (r_shadow_usingshadowmapcube)
5037                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5038                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5039                         }
5040                 }
5041                 CHECKGLERROR
5042                 break;
5043         case RENDERPATH_CGGL:
5044 #ifdef SUPPORTCG
5045                 if (gl_mesh_separatearrays.integer)
5046                 {
5047                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5048                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5049                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5050                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5051                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5052                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5053                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5054                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5055                 }
5056                 else
5057                 {
5058                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5059                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5060                 }
5061                 R_SetupShader_SetPermutationCG(mode, permutation);
5062                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5063                 if (mode == SHADERMODE_LIGHTSOURCE)
5064                 {
5065                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5066                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5067                 }
5068                 else
5069                 {
5070                         if (mode == SHADERMODE_LIGHTDIRECTION)
5071                         {
5072                                 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
5073                         }
5074                 }
5075                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5076                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5077                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5078                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5079                 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
5080                 CHECKGLERROR
5081
5082                 if (mode == SHADERMODE_LIGHTSOURCE)
5083                 {
5084                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5085                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5086                         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
5087                         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
5088                         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
5089
5090                         // additive passes are only darkened by fog, not tinted
5091                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5092                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5093                 }
5094                 else
5095                 {
5096                         if (mode == SHADERMODE_FLATCOLOR)
5097                         {
5098                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5099                         }
5100                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5101                         {
5102                                 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
5103                                 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
5104                                 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
5105                                 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
5106                                 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
5107                                 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
5108                                 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
5109                         }
5110                         else
5111                         {
5112                                 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
5113                                 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
5114                                 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
5115                                 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
5116                                 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
5117                         }
5118                         // additive passes are only darkened by fog, not tinted
5119                         if (r_cg_permutation->fp_FogColor)
5120                         {
5121                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5122                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5123                                 else
5124                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5125                                 CHECKCGERROR
5126                         }
5127                         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
5128                         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
5129                         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
5130                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5131                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5132                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5133                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5134                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5135                 }
5136                 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
5137                 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
5138                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5139                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5140                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5141                 if (r_cg_permutation->fp_Color_Pants)
5142                 {
5143                         if (rsurface.texture->pantstexture)
5144                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5145                         else
5146                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5147                         CHECKCGERROR
5148                 }
5149                 if (r_cg_permutation->fp_Color_Shirt)
5150                 {
5151                         if (rsurface.texture->shirttexture)
5152                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5153                         else
5154                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5155                         CHECKCGERROR
5156                 }
5157                 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
5158                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5159                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5160                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5161                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5162                 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
5163                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5164
5165         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5166         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5167         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5168                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5169                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5170                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5171                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5172                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5173                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5174                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5175                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5176                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5177                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5178                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5179                 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
5180                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5181                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5182                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5183                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5184                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5185                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5186                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5187                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5188                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5189                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5190                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5191                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5192                 {
5193                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5194                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5195                         if (rsurface.rtlight)
5196                         {
5197                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5198                                 if (r_shadow_usingshadowmapcube)
5199                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5200                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5201                         }
5202                 }
5203
5204                 CHECKGLERROR
5205 #endif
5206                 break;
5207         case RENDERPATH_GL13:
5208         case RENDERPATH_GL11:
5209                 break;
5210         }
5211 }
5212
5213 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5214 {
5215         // select a permutation of the lighting shader appropriate to this
5216         // combination of texture, entity, light source, and fogging, only use the
5217         // minimum features necessary to avoid wasting rendering time in the
5218         // fragment shader on features that are not being used
5219         unsigned int permutation = 0;
5220         unsigned int mode = 0;
5221         const float *lightcolorbase = rtlight->currentcolor;
5222         float ambientscale = rtlight->ambientscale;
5223         float diffusescale = rtlight->diffusescale;
5224         float specularscale = rtlight->specularscale;
5225         // this is the location of the light in view space
5226         vec3_t viewlightorigin;
5227         // this transforms from view space (camera) to light space (cubemap)
5228         matrix4x4_t viewtolight;
5229         matrix4x4_t lighttoview;
5230         float viewtolight16f[16];
5231         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5232         // light source
5233         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5234         if (rtlight->currentcubemap != r_texture_whitecube)
5235                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5236         if (diffusescale > 0)
5237                 permutation |= SHADERPERMUTATION_DIFFUSE;
5238         if (specularscale > 0)
5239         {
5240                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5241                 if (r_shadow_glossexact.integer)
5242                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5243         }
5244         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5245         {
5246                 if (r_shadow_usingshadowmaprect)
5247                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5248                 if (r_shadow_usingshadowmap2d)
5249                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5250                 if (r_shadow_usingshadowmapcube)
5251                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5252                 else if(r_shadow_shadowmapvsdct)
5253                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5254
5255                 if (r_shadow_shadowmapsampler)
5256                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5257                 if (r_shadow_shadowmappcf > 1)
5258                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5259                 else if (r_shadow_shadowmappcf)
5260                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5261         }
5262         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5263         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5264         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5265         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5266         switch(vid.renderpath)
5267         {
5268         case RENDERPATH_GL20:
5269                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5270                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5271                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5272                 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);
5273                 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);
5274                 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);
5275                 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]);
5276                 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]);
5277                 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));
5278                 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]);
5279                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5280
5281                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5282                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5283                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5284                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5285                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5286                 if (r_shadow_usingshadowmapcube)
5287                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5288                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5289                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5290                 break;
5291         case RENDERPATH_CGGL:
5292 #ifdef SUPPORTCG
5293                 R_SetupShader_SetPermutationCG(mode, permutation);
5294                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5295                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5296                 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
5297                 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
5298                 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
5299                 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
5300                 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
5301                 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
5302                 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
5303                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5304
5305                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5306                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5307                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5308                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5309                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5310                 if (r_shadow_usingshadowmapcube)
5311                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5312                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5313                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5314 #endif
5315                 break;
5316         case RENDERPATH_GL13:
5317         case RENDERPATH_GL11:
5318                 break;
5319         }
5320 }
5321
5322 #define SKINFRAME_HASH 1024
5323
5324 typedef struct
5325 {
5326         int loadsequence; // incremented each level change
5327         memexpandablearray_t array;
5328         skinframe_t *hash[SKINFRAME_HASH];
5329 }
5330 r_skinframe_t;
5331 r_skinframe_t r_skinframe;
5332
5333 void R_SkinFrame_PrepareForPurge(void)
5334 {
5335         r_skinframe.loadsequence++;
5336         // wrap it without hitting zero
5337         if (r_skinframe.loadsequence >= 200)
5338                 r_skinframe.loadsequence = 1;
5339 }
5340
5341 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5342 {
5343         if (!skinframe)
5344                 return;
5345         // mark the skinframe as used for the purging code
5346         skinframe->loadsequence = r_skinframe.loadsequence;
5347 }
5348
5349 void R_SkinFrame_Purge(void)
5350 {
5351         int i;
5352         skinframe_t *s;
5353         for (i = 0;i < SKINFRAME_HASH;i++)
5354         {
5355                 for (s = r_skinframe.hash[i];s;s = s->next)
5356                 {
5357                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5358                         {
5359                                 if (s->merged == s->base)
5360                                         s->merged = NULL;
5361                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5362                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5363                                 R_PurgeTexture(s->merged);s->merged = NULL;
5364                                 R_PurgeTexture(s->base  );s->base   = NULL;
5365                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5366                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5367                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5368                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5369                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5370                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5371                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5372                                 s->loadsequence = 0;
5373                         }
5374                 }
5375         }
5376 }
5377
5378 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5379         skinframe_t *item;
5380         char basename[MAX_QPATH];
5381
5382         Image_StripImageExtension(name, basename, sizeof(basename));
5383
5384         if( last == NULL ) {
5385                 int hashindex;
5386                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5387                 item = r_skinframe.hash[hashindex];
5388         } else {
5389                 item = last->next;
5390         }
5391
5392         // linearly search through the hash bucket
5393         for( ; item ; item = item->next ) {
5394                 if( !strcmp( item->basename, basename ) ) {
5395                         return item;
5396                 }
5397         }
5398         return NULL;
5399 }
5400
5401 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5402 {
5403         skinframe_t *item;
5404         int hashindex;
5405         char basename[MAX_QPATH];
5406
5407         Image_StripImageExtension(name, basename, sizeof(basename));
5408
5409         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5410         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5411                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5412                         break;
5413
5414         if (!item) {
5415                 rtexture_t *dyntexture;
5416                 // check whether its a dynamic texture
5417                 dyntexture = CL_GetDynTexture( basename );
5418                 if (!add && !dyntexture)
5419                         return NULL;
5420                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5421                 memset(item, 0, sizeof(*item));
5422                 strlcpy(item->basename, basename, sizeof(item->basename));
5423                 item->base = dyntexture; // either NULL or dyntexture handle
5424                 item->textureflags = textureflags;
5425                 item->comparewidth = comparewidth;
5426                 item->compareheight = compareheight;
5427                 item->comparecrc = comparecrc;
5428                 item->next = r_skinframe.hash[hashindex];
5429                 r_skinframe.hash[hashindex] = item;
5430         }
5431         else if( item->base == NULL )
5432         {
5433                 rtexture_t *dyntexture;
5434                 // check whether its a dynamic texture
5435                 // 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]
5436                 dyntexture = CL_GetDynTexture( basename );
5437                 item->base = dyntexture; // either NULL or dyntexture handle
5438         }
5439
5440         R_SkinFrame_MarkUsed(item);
5441         return item;
5442 }
5443
5444 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5445         { \
5446                 unsigned long long avgcolor[5], wsum; \
5447                 int pix, comp, w; \
5448                 avgcolor[0] = 0; \
5449                 avgcolor[1] = 0; \
5450                 avgcolor[2] = 0; \
5451                 avgcolor[3] = 0; \
5452                 avgcolor[4] = 0; \
5453                 wsum = 0; \
5454                 for(pix = 0; pix < cnt; ++pix) \
5455                 { \
5456                         w = 0; \
5457                         for(comp = 0; comp < 3; ++comp) \
5458                                 w += getpixel; \
5459                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5460                         { \
5461                                 ++wsum; \
5462                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5463                                 w = getpixel; \
5464                                 for(comp = 0; comp < 3; ++comp) \
5465                                         avgcolor[comp] += getpixel * w; \
5466                                 avgcolor[3] += w; \
5467                         } \
5468                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5469                         avgcolor[4] += getpixel; \
5470                 } \
5471                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5472                         avgcolor[3] = 1; \
5473                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5474                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5475                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5476                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5477         }
5478
5479 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5480 {
5481         int j;
5482         unsigned char *pixels;
5483         unsigned char *bumppixels;
5484         unsigned char *basepixels = NULL;
5485         int basepixels_width = 0;
5486         int basepixels_height = 0;
5487         skinframe_t *skinframe;
5488         rtexture_t *ddsbase = NULL;
5489         qboolean ddshasalpha = false;
5490         float ddsavgcolor[4];
5491         char basename[MAX_QPATH];
5492
5493         if (cls.state == ca_dedicated)
5494                 return NULL;
5495
5496         // return an existing skinframe if already loaded
5497         // if loading of the first image fails, don't make a new skinframe as it
5498         // would cause all future lookups of this to be missing
5499         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5500         if (skinframe && skinframe->base)
5501                 return skinframe;
5502
5503         Image_StripImageExtension(name, basename, sizeof(basename));
5504
5505         // check for DDS texture file first
5506         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor)))
5507         {
5508                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer);
5509                 if (basepixels == NULL)
5510                         return NULL;
5511         }
5512
5513         if (developer_loading.integer)
5514                 Con_Printf("loading skin \"%s\"\n", name);
5515
5516         // we've got some pixels to store, so really allocate this new texture now
5517         if (!skinframe)
5518                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5519         skinframe->stain = NULL;
5520         skinframe->merged = NULL;
5521         skinframe->base = NULL;
5522         skinframe->pants = NULL;
5523         skinframe->shirt = NULL;
5524         skinframe->nmap = NULL;
5525         skinframe->gloss = NULL;
5526         skinframe->glow = NULL;
5527         skinframe->fog = NULL;
5528         skinframe->reflect = NULL;
5529         skinframe->hasalpha = false;
5530
5531         if (ddsbase)
5532         {
5533                 skinframe->base = ddsbase;
5534                 skinframe->hasalpha = ddshasalpha;
5535                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5536                 if (r_loadfog && skinframe->hasalpha)
5537                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5538                 //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]);
5539         }
5540         else
5541         {
5542                 basepixels_width = image_width;
5543                 basepixels_height = image_height;
5544                 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);
5545                 if (textureflags & TEXF_ALPHA)
5546                 {
5547                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5548                         {
5549                                 if (basepixels[j] < 255)
5550                                 {
5551                                         skinframe->hasalpha = true;
5552                                         break;
5553                                 }
5554                         }
5555                         if (r_loadfog && skinframe->hasalpha)
5556                         {
5557                                 // has transparent pixels
5558                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5559                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5560                                 {
5561                                         pixels[j+0] = 255;
5562                                         pixels[j+1] = 255;
5563                                         pixels[j+2] = 255;
5564                                         pixels[j+3] = basepixels[j+3];
5565                                 }
5566                                 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);
5567                                 Mem_Free(pixels);
5568                         }
5569                 }
5570                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5571                 //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]);
5572                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5573                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5574                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5575                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5576         }
5577
5578         if (r_loaddds)
5579         {
5580                 if (r_loadnormalmap)
5581                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL);
5582                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL);
5583                 if (r_loadgloss)
5584                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL);
5585                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL);
5586                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL);
5587                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL);
5588         }
5589
5590         // _norm is the name used by tenebrae and has been adopted as standard
5591         if (r_loadnormalmap && skinframe->nmap == NULL)
5592         {
5593                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false)) != NULL)
5594                 {
5595                         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);
5596                         Mem_Free(pixels);
5597                         pixels = NULL;
5598                 }
5599                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false)) != NULL)
5600                 {
5601                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5602                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5603                         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);
5604                         Mem_Free(pixels);
5605                         Mem_Free(bumppixels);
5606                 }
5607                 else if (r_shadow_bumpscale_basetexture.value > 0)
5608                 {
5609                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5610                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5611                         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);
5612                         Mem_Free(pixels);
5613                 }
5614                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5615                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5616         }
5617
5618         // _luma is supported only for tenebrae compatibility
5619         // _glow is the preferred name
5620         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))))
5621         {
5622                 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);
5623                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5624                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5625                 Mem_Free(pixels);pixels = NULL;
5626         }
5627
5628         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5629         {
5630                 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);
5631                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5632                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5633                 Mem_Free(pixels);
5634                 pixels = NULL;
5635         }
5636
5637         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5638         {
5639                 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);
5640                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5641                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5642                 Mem_Free(pixels);
5643                 pixels = NULL;
5644         }
5645
5646         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5647         {
5648                 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);
5649                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5650                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5651                 Mem_Free(pixels);
5652                 pixels = NULL;
5653         }
5654
5655         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer)))
5656         {
5657                 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);
5658                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5659                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5660                 Mem_Free(pixels);
5661                 pixels = NULL;
5662         }
5663
5664         if (basepixels)
5665                 Mem_Free(basepixels);
5666
5667         return skinframe;
5668 }
5669
5670 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5671 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5672 {
5673         int i;
5674         unsigned char *temp1, *temp2;
5675         skinframe_t *skinframe;
5676
5677         if (cls.state == ca_dedicated)
5678                 return NULL;
5679
5680         // if already loaded just return it, otherwise make a new skinframe
5681         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5682         if (skinframe && skinframe->base)
5683                 return skinframe;
5684
5685         skinframe->stain = NULL;
5686         skinframe->merged = NULL;
5687         skinframe->base = NULL;
5688         skinframe->pants = NULL;
5689         skinframe->shirt = NULL;
5690         skinframe->nmap = NULL;
5691         skinframe->gloss = NULL;
5692         skinframe->glow = NULL;
5693         skinframe->fog = NULL;
5694         skinframe->reflect = NULL;
5695         skinframe->hasalpha = false;
5696
5697         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5698         if (!skindata)
5699                 return NULL;
5700
5701         if (developer_loading.integer)
5702                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5703
5704         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5705         {
5706                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5707                 temp2 = temp1 + width * height * 4;
5708                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5709                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5710                 Mem_Free(temp1);
5711         }
5712         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5713         if (textureflags & TEXF_ALPHA)
5714         {
5715                 for (i = 3;i < width * height * 4;i += 4)
5716                 {
5717                         if (skindata[i] < 255)
5718                         {
5719                                 skinframe->hasalpha = true;
5720                                 break;
5721                         }
5722                 }
5723                 if (r_loadfog && skinframe->hasalpha)
5724                 {
5725                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5726                         memcpy(fogpixels, skindata, width * height * 4);
5727                         for (i = 0;i < width * height * 4;i += 4)
5728                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5729                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, NULL);
5730                         Mem_Free(fogpixels);
5731                 }
5732         }
5733
5734         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5735         //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]);
5736
5737         return skinframe;
5738 }
5739
5740 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5741 {
5742         int i;
5743         int featuresmask;
5744         skinframe_t *skinframe;
5745
5746         if (cls.state == ca_dedicated)
5747                 return NULL;
5748
5749         // if already loaded just return it, otherwise make a new skinframe
5750         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5751         if (skinframe && skinframe->base)
5752                 return skinframe;
5753
5754         skinframe->stain = NULL;
5755         skinframe->merged = NULL;
5756         skinframe->base = NULL;
5757         skinframe->pants = NULL;
5758         skinframe->shirt = NULL;
5759         skinframe->nmap = NULL;
5760         skinframe->gloss = NULL;
5761         skinframe->glow = NULL;
5762         skinframe->fog = NULL;
5763         skinframe->reflect = NULL;
5764         skinframe->hasalpha = false;
5765
5766         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5767         if (!skindata)
5768                 return NULL;
5769
5770         if (developer_loading.integer)
5771                 Con_Printf("loading quake skin \"%s\"\n", name);
5772
5773         // 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)
5774         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5775         memcpy(skinframe->qpixels, skindata, width*height);
5776         skinframe->qwidth = width;
5777         skinframe->qheight = height;
5778
5779         featuresmask = 0;
5780         for (i = 0;i < width * height;i++)
5781                 featuresmask |= palette_featureflags[skindata[i]];
5782
5783         skinframe->hasalpha = false;
5784         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5785         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5786         skinframe->qgeneratemerged = true;
5787         skinframe->qgeneratebase = skinframe->qhascolormapping;
5788         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5789
5790         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5791         //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]);
5792
5793         return skinframe;
5794 }
5795
5796 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5797 {
5798         int width;
5799         int height;
5800         unsigned char *skindata;
5801
5802         if (!skinframe->qpixels)
5803                 return;
5804
5805         if (!skinframe->qhascolormapping)
5806                 colormapped = false;
5807
5808         if (colormapped)
5809         {
5810                 if (!skinframe->qgeneratebase)
5811                         return;
5812         }
5813         else
5814         {
5815                 if (!skinframe->qgeneratemerged)
5816                         return;
5817         }
5818
5819         width = skinframe->qwidth;
5820         height = skinframe->qheight;
5821         skindata = skinframe->qpixels;
5822
5823         if (skinframe->qgeneratenmap)
5824         {
5825                 unsigned char *temp1, *temp2;
5826                 skinframe->qgeneratenmap = false;
5827                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5828                 temp2 = temp1 + width * height * 4;
5829                 // use either a custom palette or the quake palette
5830                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5831                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5832                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, NULL);
5833                 Mem_Free(temp1);
5834         }
5835
5836         if (skinframe->qgenerateglow)
5837         {
5838                 skinframe->qgenerateglow = false;
5839                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_onlyfullbrights); // glow
5840         }
5841
5842         if (colormapped)
5843         {
5844                 skinframe->qgeneratebase = false;
5845                 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);
5846                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_pantsaswhite);
5847                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette_bgra_shirtaswhite);
5848         }
5849         else
5850         {
5851                 skinframe->qgeneratemerged = false;
5852                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5853         }
5854
5855         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5856         {
5857                 Mem_Free(skinframe->qpixels);
5858                 skinframe->qpixels = NULL;
5859         }
5860 }
5861
5862 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)
5863 {
5864         int i;
5865         skinframe_t *skinframe;
5866
5867         if (cls.state == ca_dedicated)
5868                 return NULL;
5869
5870         // if already loaded just return it, otherwise make a new skinframe
5871         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5872         if (skinframe && skinframe->base)
5873                 return skinframe;
5874
5875         skinframe->stain = NULL;
5876         skinframe->merged = NULL;
5877         skinframe->base = NULL;
5878         skinframe->pants = NULL;
5879         skinframe->shirt = NULL;
5880         skinframe->nmap = NULL;
5881         skinframe->gloss = NULL;
5882         skinframe->glow = NULL;
5883         skinframe->fog = NULL;
5884         skinframe->reflect = NULL;
5885         skinframe->hasalpha = false;
5886
5887         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5888         if (!skindata)
5889                 return NULL;
5890
5891         if (developer_loading.integer)
5892                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5893
5894         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, palette);
5895         if (textureflags & TEXF_ALPHA)
5896         {
5897                 for (i = 0;i < width * height;i++)
5898                 {
5899                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5900                         {
5901                                 skinframe->hasalpha = true;
5902                                 break;
5903                         }
5904                 }
5905                 if (r_loadfog && skinframe->hasalpha)
5906                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, alphapalette);
5907         }
5908
5909         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5910         //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]);
5911
5912         return skinframe;
5913 }
5914
5915 skinframe_t *R_SkinFrame_LoadMissing(void)
5916 {
5917         skinframe_t *skinframe;
5918
5919         if (cls.state == ca_dedicated)
5920                 return NULL;
5921
5922         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5923         skinframe->stain = NULL;
5924         skinframe->merged = NULL;
5925         skinframe->base = NULL;
5926         skinframe->pants = NULL;
5927         skinframe->shirt = NULL;
5928         skinframe->nmap = NULL;
5929         skinframe->gloss = NULL;
5930         skinframe->glow = NULL;
5931         skinframe->fog = NULL;
5932         skinframe->reflect = NULL;
5933         skinframe->hasalpha = false;
5934
5935         skinframe->avgcolor[0] = rand() / RAND_MAX;
5936         skinframe->avgcolor[1] = rand() / RAND_MAX;
5937         skinframe->avgcolor[2] = rand() / RAND_MAX;
5938         skinframe->avgcolor[3] = 1;
5939
5940         return skinframe;
5941 }
5942
5943 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5944 typedef struct suffixinfo_s
5945 {
5946         char *suffix;
5947         qboolean flipx, flipy, flipdiagonal;
5948 }
5949 suffixinfo_t;
5950 static suffixinfo_t suffix[3][6] =
5951 {
5952         {
5953                 {"px",   false, false, false},
5954                 {"nx",   false, false, false},
5955                 {"py",   false, false, false},
5956                 {"ny",   false, false, false},
5957                 {"pz",   false, false, false},
5958                 {"nz",   false, false, false}
5959         },
5960         {
5961                 {"posx", false, false, false},
5962                 {"negx", false, false, false},
5963                 {"posy", false, false, false},
5964                 {"negy", false, false, false},
5965                 {"posz", false, false, false},
5966                 {"negz", false, false, false}
5967         },
5968         {
5969                 {"rt",    true, false,  true},
5970                 {"lf",   false,  true,  true},
5971                 {"ft",    true,  true, false},
5972                 {"bk",   false, false, false},
5973                 {"up",    true, false,  true},
5974                 {"dn",    true, false,  true}
5975         }
5976 };
5977
5978 static int componentorder[4] = {0, 1, 2, 3};
5979
5980 rtexture_t *R_LoadCubemap(const char *basename)
5981 {
5982         int i, j, cubemapsize;
5983         unsigned char *cubemappixels, *image_buffer;
5984         rtexture_t *cubemaptexture;
5985         char name[256];
5986         // must start 0 so the first loadimagepixels has no requested width/height
5987         cubemapsize = 0;
5988         cubemappixels = NULL;
5989         cubemaptexture = NULL;
5990         // keep trying different suffix groups (posx, px, rt) until one loads
5991         for (j = 0;j < 3 && !cubemappixels;j++)
5992         {
5993                 // load the 6 images in the suffix group
5994                 for (i = 0;i < 6;i++)
5995                 {
5996                         // generate an image name based on the base and and suffix
5997                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
5998                         // load it
5999                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer)))
6000                         {
6001                                 // an image loaded, make sure width and height are equal
6002                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6003                                 {
6004                                         // if this is the first image to load successfully, allocate the cubemap memory
6005                                         if (!cubemappixels && image_width >= 1)
6006                                         {
6007                                                 cubemapsize = image_width;
6008                                                 // note this clears to black, so unavailable sides are black
6009                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6010                                         }
6011                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6012                                         if (cubemappixels)
6013                                                 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);
6014                                 }
6015                                 else
6016                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6017                                 // free the image
6018                                 Mem_Free(image_buffer);
6019                         }
6020                 }
6021         }
6022         // if a cubemap loaded, upload it
6023         if (cubemappixels)
6024         {
6025                 if (developer_loading.integer)
6026                         Con_Printf("loading cubemap \"%s\"\n", basename);
6027
6028                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR, NULL);
6029                 Mem_Free(cubemappixels);
6030         }
6031         else
6032         {
6033                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6034                 if (developer_loading.integer)
6035                 {
6036                         Con_Printf("(tried tried images ");
6037                         for (j = 0;j < 3;j++)
6038                                 for (i = 0;i < 6;i++)
6039                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6040                         Con_Print(" and was unable to find any of them).\n");
6041                 }
6042         }
6043         return cubemaptexture;
6044 }
6045
6046 rtexture_t *R_GetCubemap(const char *basename)
6047 {
6048         int i;
6049         for (i = 0;i < r_texture_numcubemaps;i++)
6050                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6051                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6052         if (i >= MAX_CUBEMAPS)
6053                 return r_texture_whitecube;
6054         r_texture_numcubemaps++;
6055         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6056         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6057         return r_texture_cubemaps[i].texture;
6058 }
6059
6060 void R_FreeCubemaps(void)
6061 {
6062         int i;
6063         for (i = 0;i < r_texture_numcubemaps;i++)
6064         {
6065                 if (developer_loading.integer)
6066                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6067                 if (r_texture_cubemaps[i].texture)
6068                         R_FreeTexture(r_texture_cubemaps[i].texture);
6069         }
6070         r_texture_numcubemaps = 0;
6071 }
6072
6073 void R_Main_FreeViewCache(void)
6074 {
6075         if (r_refdef.viewcache.entityvisible)
6076                 Mem_Free(r_refdef.viewcache.entityvisible);
6077         if (r_refdef.viewcache.world_pvsbits)
6078                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6079         if (r_refdef.viewcache.world_leafvisible)
6080                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6081         if (r_refdef.viewcache.world_surfacevisible)
6082                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6083         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6084 }
6085
6086 void R_Main_ResizeViewCache(void)
6087 {
6088         int numentities = r_refdef.scene.numentities;
6089         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6090         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6091         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6092         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6093         if (r_refdef.viewcache.maxentities < numentities)
6094         {
6095                 r_refdef.viewcache.maxentities = numentities;
6096                 if (r_refdef.viewcache.entityvisible)
6097                         Mem_Free(r_refdef.viewcache.entityvisible);
6098                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6099         }
6100         if (r_refdef.viewcache.world_numclusters != numclusters)
6101         {
6102                 r_refdef.viewcache.world_numclusters = numclusters;
6103                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6104                 if (r_refdef.viewcache.world_pvsbits)
6105                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6106                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6107         }
6108         if (r_refdef.viewcache.world_numleafs != numleafs)
6109         {
6110                 r_refdef.viewcache.world_numleafs = numleafs;
6111                 if (r_refdef.viewcache.world_leafvisible)
6112                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6113                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6114         }
6115         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6116         {
6117                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6118                 if (r_refdef.viewcache.world_surfacevisible)
6119                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6120                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6121         }
6122 }
6123
6124 extern rtexture_t *loadingscreentexture;
6125 void gl_main_start(void)
6126 {
6127         loadingscreentexture = NULL;
6128         r_texture_blanknormalmap = NULL;
6129         r_texture_white = NULL;
6130         r_texture_grey128 = NULL;
6131         r_texture_black = NULL;
6132         r_texture_whitecube = NULL;
6133         r_texture_normalizationcube = NULL;
6134         r_texture_fogattenuation = NULL;
6135         r_texture_fogheighttexture = NULL;
6136         r_texture_gammaramps = NULL;
6137         r_texture_numcubemaps = 0;
6138
6139         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6140         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6141
6142         switch(vid.renderpath)
6143         {
6144         case RENDERPATH_GL20:
6145         case RENDERPATH_CGGL:
6146                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6147                 Cvar_SetValueQuick(&gl_combine, 1);
6148                 Cvar_SetValueQuick(&r_glsl, 1);
6149                 r_loadnormalmap = true;
6150                 r_loadgloss = true;
6151                 r_loadfog = false;
6152                 break;
6153         case RENDERPATH_GL13:
6154                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6155                 Cvar_SetValueQuick(&gl_combine, 1);
6156                 Cvar_SetValueQuick(&r_glsl, 0);
6157                 r_loadnormalmap = false;
6158                 r_loadgloss = false;
6159                 r_loadfog = true;
6160                 break;
6161         case RENDERPATH_GL11:
6162                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6163                 Cvar_SetValueQuick(&gl_combine, 0);
6164                 Cvar_SetValueQuick(&r_glsl, 0);
6165                 r_loadnormalmap = false;
6166                 r_loadgloss = false;
6167                 r_loadfog = true;
6168                 break;
6169         }
6170
6171         R_AnimCache_Free();
6172         R_FrameData_Reset();
6173
6174         r_numqueries = 0;
6175         r_maxqueries = 0;
6176         memset(r_queries, 0, sizeof(r_queries));
6177
6178         r_qwskincache = NULL;
6179         r_qwskincache_size = 0;
6180
6181         // set up r_skinframe loading system for textures
6182         memset(&r_skinframe, 0, sizeof(r_skinframe));
6183         r_skinframe.loadsequence = 1;
6184         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6185
6186         r_main_texturepool = R_AllocTexturePool();
6187         R_BuildBlankTextures();
6188         R_BuildNoTexture();
6189         if (vid.support.arb_texture_cube_map)
6190         {
6191                 R_BuildWhiteCube();
6192                 R_BuildNormalizationCube();
6193         }
6194         r_texture_fogattenuation = NULL;
6195         r_texture_fogheighttexture = NULL;
6196         r_texture_gammaramps = NULL;
6197         //r_texture_fogintensity = NULL;
6198         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6199         memset(&r_waterstate, 0, sizeof(r_waterstate));
6200         r_glsl_permutation = NULL;
6201         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6202         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6203         glslshaderstring = NULL;
6204 #ifdef SUPPORTCG
6205         r_cg_permutation = NULL;
6206         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6207         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6208         cgshaderstring = NULL;
6209 #endif
6210         memset(&r_svbsp, 0, sizeof (r_svbsp));
6211
6212         r_refdef.fogmasktable_density = 0;
6213 }
6214
6215 void gl_main_shutdown(void)
6216 {
6217         R_AnimCache_Free();
6218         R_FrameData_Reset();
6219
6220         R_Main_FreeViewCache();
6221
6222         if (r_maxqueries)
6223                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6224
6225         r_numqueries = 0;
6226         r_maxqueries = 0;
6227         memset(r_queries, 0, sizeof(r_queries));
6228
6229         r_qwskincache = NULL;
6230         r_qwskincache_size = 0;
6231
6232         // clear out the r_skinframe state
6233         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6234         memset(&r_skinframe, 0, sizeof(r_skinframe));
6235
6236         if (r_svbsp.nodes)
6237                 Mem_Free(r_svbsp.nodes);
6238         memset(&r_svbsp, 0, sizeof (r_svbsp));
6239         R_FreeTexturePool(&r_main_texturepool);
6240         loadingscreentexture = NULL;
6241         r_texture_blanknormalmap = NULL;
6242         r_texture_white = NULL;
6243         r_texture_grey128 = NULL;
6244         r_texture_black = NULL;
6245         r_texture_whitecube = NULL;
6246         r_texture_normalizationcube = NULL;
6247         r_texture_fogattenuation = NULL;
6248         r_texture_fogheighttexture = NULL;
6249         r_texture_gammaramps = NULL;
6250         r_texture_numcubemaps = 0;
6251         //r_texture_fogintensity = NULL;
6252         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6253         memset(&r_waterstate, 0, sizeof(r_waterstate));
6254         r_glsl_permutation = NULL;
6255         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6256         glslshaderstring = NULL;
6257 #ifdef SUPPORTCG
6258         r_cg_permutation = NULL;
6259         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6260         cgshaderstring = NULL;
6261 #endif
6262         R_GLSL_Restart_f();
6263 }
6264
6265 extern void CL_ParseEntityLump(char *entitystring);
6266 void gl_main_newmap(void)
6267 {
6268         // FIXME: move this code to client
6269         int l;
6270         char *entities, entname[MAX_QPATH];
6271         if (r_qwskincache)
6272                 Mem_Free(r_qwskincache);
6273         r_qwskincache = NULL;
6274         r_qwskincache_size = 0;
6275         if (cl.worldmodel)
6276         {
6277                 strlcpy(entname, cl.worldmodel->name, sizeof(entname));
6278                 l = (int)strlen(entname) - 4;
6279                 if (l >= 0 && !strcmp(entname + l, ".bsp"))
6280                 {
6281                         memcpy(entname + l, ".ent", 5);
6282                         if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6283                         {
6284                                 CL_ParseEntityLump(entities);
6285                                 Mem_Free(entities);
6286                                 return;
6287                         }
6288                 }
6289                 if (cl.worldmodel->brush.entities)
6290                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6291         }
6292         R_Main_FreeViewCache();
6293
6294         R_FrameData_Reset();
6295 }
6296
6297 void GL_Main_Init(void)
6298 {
6299         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6300
6301         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6302         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6303         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6304         if (gamemode == GAME_NEHAHRA)
6305         {
6306                 Cvar_RegisterVariable (&gl_fogenable);
6307                 Cvar_RegisterVariable (&gl_fogdensity);
6308                 Cvar_RegisterVariable (&gl_fogred);
6309                 Cvar_RegisterVariable (&gl_foggreen);
6310                 Cvar_RegisterVariable (&gl_fogblue);
6311                 Cvar_RegisterVariable (&gl_fogstart);
6312                 Cvar_RegisterVariable (&gl_fogend);
6313                 Cvar_RegisterVariable (&gl_skyclip);
6314         }
6315         Cvar_RegisterVariable(&r_motionblur);
6316         Cvar_RegisterVariable(&r_motionblur_maxblur);
6317         Cvar_RegisterVariable(&r_motionblur_bmin);
6318         Cvar_RegisterVariable(&r_motionblur_vmin);
6319         Cvar_RegisterVariable(&r_motionblur_vmax);
6320         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6321         Cvar_RegisterVariable(&r_motionblur_randomize);
6322         Cvar_RegisterVariable(&r_damageblur);
6323         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6324         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6325         Cvar_RegisterVariable(&r_equalize_entities_by);
6326         Cvar_RegisterVariable(&r_equalize_entities_to);
6327         Cvar_RegisterVariable(&r_depthfirst);
6328         Cvar_RegisterVariable(&r_useinfinitefarclip);
6329         Cvar_RegisterVariable(&r_farclip_base);
6330         Cvar_RegisterVariable(&r_farclip_world);
6331         Cvar_RegisterVariable(&r_nearclip);
6332         Cvar_RegisterVariable(&r_showbboxes);
6333         Cvar_RegisterVariable(&r_showsurfaces);
6334         Cvar_RegisterVariable(&r_showtris);
6335         Cvar_RegisterVariable(&r_shownormals);
6336         Cvar_RegisterVariable(&r_showlighting);
6337         Cvar_RegisterVariable(&r_showshadowvolumes);
6338         Cvar_RegisterVariable(&r_showcollisionbrushes);
6339         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6340         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6341         Cvar_RegisterVariable(&r_showdisabledepthtest);
6342         Cvar_RegisterVariable(&r_drawportals);
6343         Cvar_RegisterVariable(&r_drawentities);
6344         Cvar_RegisterVariable(&r_cullentities_trace);
6345         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6346         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6347         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6348         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6349         Cvar_RegisterVariable(&r_drawviewmodel);
6350         Cvar_RegisterVariable(&r_drawexteriormodel);
6351         Cvar_RegisterVariable(&r_speeds);
6352         Cvar_RegisterVariable(&r_fullbrights);
6353         Cvar_RegisterVariable(&r_wateralpha);
6354         Cvar_RegisterVariable(&r_dynamic);
6355         Cvar_RegisterVariable(&r_fullbright);
6356         Cvar_RegisterVariable(&r_shadows);
6357         Cvar_RegisterVariable(&r_shadows_darken);
6358         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6359         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6360         Cvar_RegisterVariable(&r_shadows_throwdistance);
6361         Cvar_RegisterVariable(&r_shadows_throwdirection);
6362         Cvar_RegisterVariable(&r_shadows_focus);
6363         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6364         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6365         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6366         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6367         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6368         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6369         Cvar_RegisterVariable(&r_fog_exp2);
6370         Cvar_RegisterVariable(&r_drawfog);
6371         Cvar_RegisterVariable(&r_transparentdepthmasking);
6372         Cvar_RegisterVariable(&r_texture_dds_load);
6373         Cvar_RegisterVariable(&r_texture_dds_save);
6374         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6375         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6376         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6377         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6378         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6379         Cvar_RegisterVariable(&r_textureunits);
6380         Cvar_RegisterVariable(&gl_combine);
6381         Cvar_RegisterVariable(&r_glsl);
6382         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6383         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6384         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6385         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6386         Cvar_RegisterVariable(&r_glsl_postprocess);
6387         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6388         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6389         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6390         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6391         Cvar_RegisterVariable(&r_water);
6392         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6393         Cvar_RegisterVariable(&r_water_clippingplanebias);
6394         Cvar_RegisterVariable(&r_water_refractdistort);
6395         Cvar_RegisterVariable(&r_water_reflectdistort);
6396         Cvar_RegisterVariable(&r_lerpsprites);
6397         Cvar_RegisterVariable(&r_lerpmodels);
6398         Cvar_RegisterVariable(&r_lerplightstyles);
6399         Cvar_RegisterVariable(&r_waterscroll);
6400         Cvar_RegisterVariable(&r_bloom);
6401         Cvar_RegisterVariable(&r_bloom_colorscale);
6402         Cvar_RegisterVariable(&r_bloom_brighten);
6403         Cvar_RegisterVariable(&r_bloom_blur);
6404         Cvar_RegisterVariable(&r_bloom_resolution);
6405         Cvar_RegisterVariable(&r_bloom_colorexponent);
6406         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6407         Cvar_RegisterVariable(&r_hdr);
6408         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6409         Cvar_RegisterVariable(&r_hdr_glowintensity);
6410         Cvar_RegisterVariable(&r_hdr_range);
6411         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6412         Cvar_RegisterVariable(&developer_texturelogging);
6413         Cvar_RegisterVariable(&gl_lightmaps);
6414         Cvar_RegisterVariable(&r_test);
6415         Cvar_RegisterVariable(&r_glsl_saturation);
6416         Cvar_RegisterVariable(&r_framedatasize);
6417         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6418                 Cvar_SetValue("r_fullbrights", 0);
6419         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6420
6421         Cvar_RegisterVariable(&r_track_sprites);
6422         Cvar_RegisterVariable(&r_track_sprites_flags);
6423         Cvar_RegisterVariable(&r_track_sprites_scalew);
6424         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6425         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6426         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6427 }
6428
6429 extern void R_Textures_Init(void);
6430 extern void GL_Draw_Init(void);
6431 extern void GL_Main_Init(void);
6432 extern void R_Shadow_Init(void);
6433 extern void R_Sky_Init(void);
6434 extern void GL_Surf_Init(void);
6435 extern void R_Particles_Init(void);
6436 extern void R_Explosion_Init(void);
6437 extern void gl_backend_init(void);
6438 extern void Sbar_Init(void);
6439 extern void R_LightningBeams_Init(void);
6440 extern void Mod_RenderInit(void);
6441 extern void Font_Init(void);
6442
6443 void Render_Init(void)
6444 {
6445         gl_backend_init();
6446         R_Textures_Init();
6447         GL_Main_Init();
6448         Font_Init();
6449         GL_Draw_Init();
6450         R_Shadow_Init();
6451         R_Sky_Init();
6452         GL_Surf_Init();
6453         Sbar_Init();
6454         R_Particles_Init();
6455         R_Explosion_Init();
6456         R_LightningBeams_Init();
6457         Mod_RenderInit();
6458 }
6459
6460 /*
6461 ===============
6462 GL_Init
6463 ===============
6464 */
6465 extern char *ENGINE_EXTENSIONS;
6466 void GL_Init (void)
6467 {
6468         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6469         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6470         gl_version = (const char *)qglGetString(GL_VERSION);
6471         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6472
6473         if (!gl_extensions)
6474                 gl_extensions = "";
6475         if (!gl_platformextensions)
6476                 gl_platformextensions = "";
6477
6478         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6479         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6480         Con_Printf("GL_VERSION: %s\n", gl_version);
6481         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6482         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6483
6484         VID_CheckExtensions();
6485
6486         // LordHavoc: report supported extensions
6487         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6488
6489         // clear to black (loading plaque will be seen over this)
6490         CHECKGLERROR
6491         qglClearColor(0,0,0,1);CHECKGLERROR
6492         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6493 }
6494
6495 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6496 {
6497         int i;
6498         mplane_t *p;
6499         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6500         {
6501                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6502                 if (i == 4)
6503                         continue;
6504                 p = r_refdef.view.frustum + i;
6505                 switch(p->signbits)
6506                 {
6507                 default:
6508                 case 0:
6509                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6510                                 return true;
6511                         break;
6512                 case 1:
6513                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6514                                 return true;
6515                         break;
6516                 case 2:
6517                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6518                                 return true;
6519                         break;
6520                 case 3:
6521                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6522                                 return true;
6523                         break;
6524                 case 4:
6525                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6526                                 return true;
6527                         break;
6528                 case 5:
6529                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6530                                 return true;
6531                         break;
6532                 case 6:
6533                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6534                                 return true;
6535                         break;
6536                 case 7:
6537                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6538                                 return true;
6539                         break;
6540                 }
6541         }
6542         return false;
6543 }
6544
6545 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6546 {
6547         int i;
6548         const mplane_t *p;
6549         for (i = 0;i < numplanes;i++)
6550         {
6551                 p = planes + i;
6552                 switch(p->signbits)
6553                 {
6554                 default:
6555                 case 0:
6556                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6557                                 return true;
6558                         break;
6559                 case 1:
6560                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6561                                 return true;
6562                         break;
6563                 case 2:
6564                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6565                                 return true;
6566                         break;
6567                 case 3:
6568                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6569                                 return true;
6570                         break;
6571                 case 4:
6572                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6573                                 return true;
6574                         break;
6575                 case 5:
6576                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6577                                 return true;
6578                         break;
6579                 case 6:
6580                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6581                                 return true;
6582                         break;
6583                 case 7:
6584                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6585                                 return true;
6586                         break;
6587                 }
6588         }
6589         return false;
6590 }
6591
6592 //==================================================================================
6593
6594 // LordHavoc: this stores temporary data used within the same frame
6595
6596 qboolean r_framedata_failed;
6597 static size_t r_framedata_size;
6598 static size_t r_framedata_current;
6599 static void *r_framedata_base;
6600
6601 void R_FrameData_Reset(void)
6602 {
6603         if (r_framedata_base)
6604                 Mem_Free(r_framedata_base);
6605         r_framedata_base = NULL;
6606         r_framedata_size = 0;
6607         r_framedata_current = 0;
6608         r_framedata_failed = false;
6609 }
6610
6611 void R_FrameData_NewFrame(void)
6612 {
6613         size_t wantedsize;
6614         if (r_framedata_failed)
6615                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6616         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6617         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6618         if (r_framedata_size != wantedsize)
6619         {
6620                 r_framedata_size = wantedsize;
6621                 if (r_framedata_base)
6622                         Mem_Free(r_framedata_base);
6623                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6624         }
6625         r_framedata_current = 0;
6626         r_framedata_failed = false;
6627 }
6628
6629 void *R_FrameData_Alloc(size_t size)
6630 {
6631         void *data;
6632
6633         // align to 16 byte boundary
6634         size = (size + 15) & ~15;
6635         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6636         r_framedata_current += size;
6637
6638         // check overflow
6639         if (r_framedata_current > r_framedata_size)
6640                 r_framedata_failed = true;
6641
6642         // return NULL on everything after a failure
6643         if (r_framedata_failed)
6644                 return NULL;
6645
6646         return data;
6647 }
6648
6649 void *R_FrameData_Store(size_t size, void *data)
6650 {
6651         void *d = R_FrameData_Alloc(size);
6652         if (d)
6653                 memcpy(d, data, size);
6654         return d;
6655 }
6656
6657 //==================================================================================
6658
6659 // LordHavoc: animcache originally written by Echon, rewritten since then
6660
6661 /**
6662  * Animation cache prevents re-generating mesh data for an animated model
6663  * multiple times in one frame for lighting, shadowing, reflections, etc.
6664  */
6665
6666 void R_AnimCache_Free(void)
6667 {
6668 }
6669
6670 void R_AnimCache_ClearCache(void)
6671 {
6672         int i;
6673         entity_render_t *ent;
6674
6675         for (i = 0;i < r_refdef.scene.numentities;i++)
6676         {
6677                 ent = r_refdef.scene.entities[i];
6678                 ent->animcache_vertex3f = NULL;
6679                 ent->animcache_normal3f = NULL;
6680                 ent->animcache_svector3f = NULL;
6681                 ent->animcache_tvector3f = NULL;
6682                 ent->animcache_vertexposition = NULL;
6683                 ent->animcache_vertexmesh = NULL;
6684                 ent->animcache_vertexpositionbuffer = NULL;
6685                 ent->animcache_vertexmeshbuffer = NULL;
6686         }
6687 }
6688
6689 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
6690 {
6691         int i;
6692         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
6693                 ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
6694         if (!ent->animcache_vertexposition)
6695                 ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
6696         if (ent->animcache_vertexposition)
6697         {
6698                 for (i = 0;i < numvertices;i++)
6699                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
6700                 // TODO: upload vertex buffer?
6701         }
6702         if (ent->animcache_vertexmesh)
6703         {
6704                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
6705                 for (i = 0;i < numvertices;i++)
6706                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
6707                 if (ent->animcache_svector3f)
6708                         for (i = 0;i < numvertices;i++)
6709                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
6710                 if (ent->animcache_tvector3f)
6711                         for (i = 0;i < numvertices;i++)
6712                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
6713                 if (ent->animcache_normal3f)
6714                         for (i = 0;i < numvertices;i++)
6715                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
6716                 // TODO: upload vertex buffer?
6717         }
6718 }
6719
6720 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6721 {
6722         dp_model_t *model = ent->model;
6723         int numvertices;
6724         // see if it's already cached this frame
6725         if (ent->animcache_vertex3f)
6726         {
6727                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
6728                 if (wantnormals || wanttangents)
6729                 {
6730                         if (ent->animcache_normal3f)
6731                                 wantnormals = false;
6732                         if (ent->animcache_svector3f)
6733                                 wanttangents = false;
6734                         if (wantnormals || wanttangents)
6735                         {
6736                                 numvertices = model->surfmesh.num_vertices;
6737                                 if (wantnormals)
6738                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6739                                 if (wanttangents)
6740                                 {
6741                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6742                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6743                                 }
6744                                 if (!r_framedata_failed)
6745                                 {
6746                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6747                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6748                                 }
6749                         }
6750                 }
6751         }
6752         else
6753         {
6754                 // see if this ent is worth caching
6755                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6756                         return false;
6757                 // get some memory for this entity and generate mesh data
6758                 numvertices = model->surfmesh.num_vertices;
6759                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6760                 if (wantnormals)
6761                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6762                 if (wanttangents)
6763                 {
6764                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6765                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6766                 }
6767                 if (!r_framedata_failed)
6768                 {
6769                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6770                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6771                 }
6772         }
6773         return !r_framedata_failed;
6774 }
6775
6776 void R_AnimCache_CacheVisibleEntities(void)
6777 {
6778         int i;
6779         qboolean wantnormals = true;
6780         qboolean wanttangents = !r_showsurfaces.integer;
6781
6782         switch(vid.renderpath)
6783         {
6784         case RENDERPATH_GL20:
6785         case RENDERPATH_CGGL:
6786                 break;
6787         case RENDERPATH_GL13:
6788         case RENDERPATH_GL11:
6789                 wanttangents = false;
6790                 break;
6791         }
6792
6793         if (r_shownormals.integer)
6794                 wanttangents = wantnormals = true;
6795
6796         // TODO: thread this
6797         // NOTE: R_PrepareRTLights() also caches entities
6798
6799         for (i = 0;i < r_refdef.scene.numentities;i++)
6800                 if (r_refdef.viewcache.entityvisible[i])
6801                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6802 }
6803
6804 //==================================================================================
6805
6806 static void R_View_UpdateEntityLighting (void)
6807 {
6808         int i;
6809         entity_render_t *ent;
6810         vec3_t tempdiffusenormal, avg;
6811         vec_t f, fa, fd, fdd;
6812         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6813
6814         for (i = 0;i < r_refdef.scene.numentities;i++)
6815         {
6816                 ent = r_refdef.scene.entities[i];
6817
6818                 // skip unseen models
6819                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6820                         continue;
6821
6822                 // skip bsp models
6823                 if (ent->model && ent->model->brush.num_leafs)
6824                 {
6825                         // TODO: use modellight for r_ambient settings on world?
6826                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6827                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6828                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6829                         continue;
6830                 }
6831
6832                 // fetch the lighting from the worldmodel data
6833                 VectorClear(ent->modellight_ambient);
6834                 VectorClear(ent->modellight_diffuse);
6835                 VectorClear(tempdiffusenormal);
6836                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6837                 {
6838                         vec3_t org;
6839                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6840                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6841                         if(ent->flags & RENDER_EQUALIZE)
6842                         {
6843                                 // first fix up ambient lighting...
6844                                 if(r_equalize_entities_minambient.value > 0)
6845                                 {
6846                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6847                                         if(fd > 0)
6848                                         {
6849                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6850                                                 if(fa < r_equalize_entities_minambient.value * fd)
6851                                                 {
6852                                                         // solve:
6853                                                         //   fa'/fd' = minambient
6854                                                         //   fa'+0.25*fd' = fa+0.25*fd
6855                                                         //   ...
6856                                                         //   fa' = fd' * minambient
6857                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6858                                                         //   ...
6859                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6860                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6861                                                         //   ...
6862                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6863                                                         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
6864                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6865                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6866                                                 }
6867                                         }
6868                                 }
6869
6870                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6871                                 {
6872                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6873                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6874                                         if(f > 0)
6875                                         {
6876                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6877                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6878                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6879                                         }
6880                                 }
6881                         }
6882                 }
6883                 else // highly rare
6884                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6885
6886                 // move the light direction into modelspace coordinates for lighting code
6887                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6888                 if(VectorLength2(ent->modellight_lightdir) == 0)
6889                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6890                 VectorNormalize(ent->modellight_lightdir);
6891         }
6892 }
6893
6894 #define MAX_LINEOFSIGHTTRACES 64
6895
6896 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6897 {
6898         int i;
6899         vec3_t boxmins, boxmaxs;
6900         vec3_t start;
6901         vec3_t end;
6902         dp_model_t *model = r_refdef.scene.worldmodel;
6903
6904         if (!model || !model->brush.TraceLineOfSight)
6905                 return true;
6906
6907         // expand the box a little
6908         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6909         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6910         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6911         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6912         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6913         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6914
6915         // return true if eye is inside enlarged box
6916         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6917                 return true;
6918
6919         // try center
6920         VectorCopy(eye, start);
6921         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6922         if (model->brush.TraceLineOfSight(model, start, end))
6923                 return true;
6924
6925         // try various random positions
6926         for (i = 0;i < numsamples;i++)
6927         {
6928                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6929                 if (model->brush.TraceLineOfSight(model, start, end))
6930                         return true;
6931         }
6932
6933         return false;
6934 }
6935
6936
6937 static void R_View_UpdateEntityVisible (void)
6938 {
6939         int i;
6940         int renderimask;
6941         int samples;
6942         entity_render_t *ent;
6943
6944         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6945                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6946                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6947                 :                                                          RENDER_EXTERIORMODEL;
6948         if (!r_drawviewmodel.integer)
6949                 renderimask |= RENDER_VIEWMODEL;
6950         if (!r_drawexteriormodel.integer)
6951                 renderimask |= RENDER_EXTERIORMODEL;
6952         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6953         {
6954                 // worldmodel can check visibility
6955                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6956                 for (i = 0;i < r_refdef.scene.numentities;i++)
6957                 {
6958                         ent = r_refdef.scene.entities[i];
6959                         if (!(ent->flags & renderimask))
6960                         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)))
6961                         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))
6962                                 r_refdef.viewcache.entityvisible[i] = true;
6963                 }
6964                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
6965                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
6966                 {
6967                         for (i = 0;i < r_refdef.scene.numentities;i++)
6968                         {
6969                                 ent = r_refdef.scene.entities[i];
6970                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
6971                                 {
6972                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
6973                                         if (samples < 0)
6974                                                 continue; // temp entities do pvs only
6975                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
6976                                                 ent->last_trace_visibility = realtime;
6977                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
6978                                                 r_refdef.viewcache.entityvisible[i] = 0;
6979                                 }
6980                         }
6981                 }
6982         }
6983         else
6984         {
6985                 // no worldmodel or it can't check visibility
6986                 for (i = 0;i < r_refdef.scene.numentities;i++)
6987                 {
6988                         ent = r_refdef.scene.entities[i];
6989                         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));
6990                 }
6991         }
6992 }
6993
6994 /// only used if skyrendermasked, and normally returns false
6995 int R_DrawBrushModelsSky (void)
6996 {
6997         int i, sky;
6998         entity_render_t *ent;
6999
7000         sky = false;
7001         for (i = 0;i < r_refdef.scene.numentities;i++)
7002         {
7003                 if (!r_refdef.viewcache.entityvisible[i])
7004                         continue;
7005                 ent = r_refdef.scene.entities[i];
7006                 if (!ent->model || !ent->model->DrawSky)
7007                         continue;
7008                 ent->model->DrawSky(ent);
7009                 sky = true;
7010         }
7011         return sky;
7012 }
7013
7014 static void R_DrawNoModel(entity_render_t *ent);
7015 static void R_DrawModels(void)
7016 {
7017         int i;
7018         entity_render_t *ent;
7019
7020         for (i = 0;i < r_refdef.scene.numentities;i++)
7021         {
7022                 if (!r_refdef.viewcache.entityvisible[i])
7023                         continue;
7024                 ent = r_refdef.scene.entities[i];
7025                 r_refdef.stats.entities++;
7026                 if (ent->model && ent->model->Draw != NULL)
7027                         ent->model->Draw(ent);
7028                 else
7029                         R_DrawNoModel(ent);
7030         }
7031 }
7032
7033 static void R_DrawModelsDepth(void)
7034 {
7035         int i;
7036         entity_render_t *ent;
7037
7038         for (i = 0;i < r_refdef.scene.numentities;i++)
7039         {
7040                 if (!r_refdef.viewcache.entityvisible[i])
7041                         continue;
7042                 ent = r_refdef.scene.entities[i];
7043                 if (ent->model && ent->model->DrawDepth != NULL)
7044                         ent->model->DrawDepth(ent);
7045         }
7046 }
7047
7048 static void R_DrawModelsDebug(void)
7049 {
7050         int i;
7051         entity_render_t *ent;
7052
7053         for (i = 0;i < r_refdef.scene.numentities;i++)
7054         {
7055                 if (!r_refdef.viewcache.entityvisible[i])
7056                         continue;
7057                 ent = r_refdef.scene.entities[i];
7058                 if (ent->model && ent->model->DrawDebug != NULL)
7059                         ent->model->DrawDebug(ent);
7060         }
7061 }
7062
7063 static void R_DrawModelsAddWaterPlanes(void)
7064 {
7065         int i;
7066         entity_render_t *ent;
7067
7068         for (i = 0;i < r_refdef.scene.numentities;i++)
7069         {
7070                 if (!r_refdef.viewcache.entityvisible[i])
7071                         continue;
7072                 ent = r_refdef.scene.entities[i];
7073                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7074                         ent->model->DrawAddWaterPlanes(ent);
7075         }
7076 }
7077
7078 static void R_View_SetFrustum(void)
7079 {
7080         int i;
7081         double slopex, slopey;
7082         vec3_t forward, left, up, origin;
7083
7084         // we can't trust r_refdef.view.forward and friends in reflected scenes
7085         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7086
7087 #if 0
7088         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7089         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7090         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7091         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7092         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7093         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7094         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7095         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7096         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7097         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7098         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7099         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7100 #endif
7101
7102 #if 0
7103         zNear = r_refdef.nearclip;
7104         nudge = 1.0 - 1.0 / (1<<23);
7105         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7106         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7107         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7108         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7109         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7110         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7111         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7112         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7113 #endif
7114
7115
7116
7117 #if 0
7118         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7119         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7120         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7121         r_refdef.view.frustum[0].dist = m[15] - m[12];
7122
7123         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7124         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7125         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7126         r_refdef.view.frustum[1].dist = m[15] + m[12];
7127
7128         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7129         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7130         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7131         r_refdef.view.frustum[2].dist = m[15] - m[13];
7132
7133         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7134         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7135         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7136         r_refdef.view.frustum[3].dist = m[15] + m[13];
7137
7138         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7139         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7140         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7141         r_refdef.view.frustum[4].dist = m[15] - m[14];
7142
7143         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7144         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7145         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7146         r_refdef.view.frustum[5].dist = m[15] + m[14];
7147 #endif
7148
7149         if (r_refdef.view.useperspective)
7150         {
7151                 slopex = 1.0 / r_refdef.view.frustum_x;
7152                 slopey = 1.0 / r_refdef.view.frustum_y;
7153                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7154                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7155                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7156                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7157                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7158
7159                 // Leaving those out was a mistake, those were in the old code, and they
7160                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7161                 // I couldn't reproduce it after adding those normalizations. --blub
7162                 VectorNormalize(r_refdef.view.frustum[0].normal);
7163                 VectorNormalize(r_refdef.view.frustum[1].normal);
7164                 VectorNormalize(r_refdef.view.frustum[2].normal);
7165                 VectorNormalize(r_refdef.view.frustum[3].normal);
7166
7167                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7168                 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]);
7169                 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]);
7170                 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]);
7171                 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]);
7172
7173                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7174                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7175                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7176                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7177                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7178         }
7179         else
7180         {
7181                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7182                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7183                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7184                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7185                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7186                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7187                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7188                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7189                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7190                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7191         }
7192         r_refdef.view.numfrustumplanes = 5;
7193
7194         if (r_refdef.view.useclipplane)
7195         {
7196                 r_refdef.view.numfrustumplanes = 6;
7197                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7198         }
7199
7200         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7201                 PlaneClassify(r_refdef.view.frustum + i);
7202
7203         // LordHavoc: note to all quake engine coders, Quake had a special case
7204         // for 90 degrees which assumed a square view (wrong), so I removed it,
7205         // Quake2 has it disabled as well.
7206
7207         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7208         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7209         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7210         //PlaneClassify(&frustum[0]);
7211
7212         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7213         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7214         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7215         //PlaneClassify(&frustum[1]);
7216
7217         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7218         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7219         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7220         //PlaneClassify(&frustum[2]);
7221
7222         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7223         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7224         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7225         //PlaneClassify(&frustum[3]);
7226
7227         // nearclip plane
7228         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7229         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7230         //PlaneClassify(&frustum[4]);
7231 }
7232
7233 void R_View_Update(void)
7234 {
7235         R_Main_ResizeViewCache();
7236         R_View_SetFrustum();
7237         R_View_WorldVisibility(r_refdef.view.useclipplane);
7238         R_View_UpdateEntityVisible();
7239         R_View_UpdateEntityLighting();
7240 }
7241
7242 void R_SetupView(qboolean allowwaterclippingplane)
7243 {
7244         const float *customclipplane = NULL;
7245         float plane[4];
7246         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7247         {
7248                 // LordHavoc: couldn't figure out how to make this approach the
7249                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7250                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7251                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7252                         dist = r_refdef.view.clipplane.dist;
7253                 plane[0] = r_refdef.view.clipplane.normal[0];
7254                 plane[1] = r_refdef.view.clipplane.normal[1];
7255                 plane[2] = r_refdef.view.clipplane.normal[2];
7256                 plane[3] = dist;
7257                 customclipplane = plane;
7258         }
7259
7260         if (!r_refdef.view.useperspective)
7261                 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);
7262         else if (vid.stencil && r_useinfinitefarclip.integer)
7263                 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);
7264         else
7265                 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);
7266         R_SetViewport(&r_refdef.view.viewport);
7267 }
7268
7269 void R_EntityMatrix(const matrix4x4_t *matrix)
7270 {
7271         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7272         {
7273                 gl_modelmatrixchanged = false;
7274                 gl_modelmatrix = *matrix;
7275                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7276                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7277                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7278                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7279                 CHECKGLERROR
7280                 switch(vid.renderpath)
7281                 {
7282                 case RENDERPATH_GL20:
7283                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7284                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7285                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7286                         break;
7287                 case RENDERPATH_CGGL:
7288 #ifdef SUPPORTCG
7289                         CHECKCGERROR
7290                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7291                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7292                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7293 #endif
7294                         break;
7295                 case RENDERPATH_GL13:
7296                 case RENDERPATH_GL11:
7297                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7298                         break;
7299                 }
7300         }
7301 }
7302
7303 void R_ResetViewRendering2D(void)
7304 {
7305         r_viewport_t viewport;
7306         DrawQ_Finish();
7307
7308         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7309         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);
7310         R_SetViewport(&viewport);
7311         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7312         GL_Color(1, 1, 1, 1);
7313         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7314         GL_BlendFunc(GL_ONE, GL_ZERO);
7315         GL_AlphaTest(false);
7316         GL_ScissorTest(false);
7317         GL_DepthMask(false);
7318         GL_DepthRange(0, 1);
7319         GL_DepthTest(false);
7320         R_EntityMatrix(&identitymatrix);
7321         R_Mesh_ResetTextureState();
7322         GL_PolygonOffset(0, 0);
7323         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7324         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7325         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7326         qglStencilMask(~0);CHECKGLERROR
7327         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7328         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7329         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7330 }
7331
7332 void R_ResetViewRendering3D(void)
7333 {
7334         DrawQ_Finish();
7335
7336         R_SetupView(true);
7337         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7338         GL_Color(1, 1, 1, 1);
7339         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7340         GL_BlendFunc(GL_ONE, GL_ZERO);
7341         GL_AlphaTest(false);
7342         GL_ScissorTest(true);
7343         GL_DepthMask(true);
7344         GL_DepthRange(0, 1);
7345         GL_DepthTest(true);
7346         R_EntityMatrix(&identitymatrix);
7347         R_Mesh_ResetTextureState();
7348         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7349         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7350         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7351         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7352         qglStencilMask(~0);CHECKGLERROR
7353         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7354         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7355         GL_CullFace(r_refdef.view.cullface_back);
7356 }
7357
7358 /*
7359 ================
7360 R_RenderView_UpdateViewVectors
7361 ================
7362 */
7363 static void R_RenderView_UpdateViewVectors(void)
7364 {
7365         // break apart the view matrix into vectors for various purposes
7366         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7367         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7368         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7369         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7370         // make an inverted copy of the view matrix for tracking sprites
7371         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7372 }
7373
7374 void R_RenderScene(void);
7375 void R_RenderWaterPlanes(void);
7376
7377 static void R_Water_StartFrame(void)
7378 {
7379         int i;
7380         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7381         r_waterstate_waterplane_t *p;
7382
7383         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7384                 return;
7385
7386         switch(vid.renderpath)
7387         {
7388         case RENDERPATH_GL20:
7389         case RENDERPATH_CGGL:
7390                 break;
7391         case RENDERPATH_GL13:
7392         case RENDERPATH_GL11:
7393                 return;
7394         }
7395
7396         // set waterwidth and waterheight to the water resolution that will be
7397         // used (often less than the screen resolution for faster rendering)
7398         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7399         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7400
7401         // calculate desired texture sizes
7402         // can't use water if the card does not support the texture size
7403         if (!r_water.integer || r_showsurfaces.integer)
7404                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7405         else if (vid.support.arb_texture_non_power_of_two)
7406         {
7407                 texturewidth = waterwidth;
7408                 textureheight = waterheight;
7409                 camerawidth = waterwidth;
7410                 cameraheight = waterheight;
7411         }
7412         else
7413         {
7414                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7415                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7416                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7417                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7418         }
7419
7420         // allocate textures as needed
7421         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7422         {
7423                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7424                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7425                 {
7426                         if (p->texture_refraction)
7427                                 R_FreeTexture(p->texture_refraction);
7428                         p->texture_refraction = NULL;
7429                         if (p->texture_reflection)
7430                                 R_FreeTexture(p->texture_reflection);
7431                         p->texture_reflection = NULL;
7432                         if (p->texture_camera)
7433                                 R_FreeTexture(p->texture_camera);
7434                         p->texture_camera = NULL;
7435                 }
7436                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7437                 r_waterstate.texturewidth = texturewidth;
7438                 r_waterstate.textureheight = textureheight;
7439                 r_waterstate.camerawidth = camerawidth;
7440                 r_waterstate.cameraheight = cameraheight;
7441         }
7442
7443         if (r_waterstate.texturewidth)
7444         {
7445                 r_waterstate.enabled = true;
7446
7447                 // when doing a reduced render (HDR) we want to use a smaller area
7448                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7449                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7450
7451                 // set up variables that will be used in shader setup
7452                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7453                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7454                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7455                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7456         }
7457
7458         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7459         r_waterstate.numwaterplanes = 0;
7460 }
7461
7462 void R_Water_AddWaterPlane(msurface_t *surface)
7463 {
7464         int triangleindex, planeindex;
7465         const int *e;
7466         vec3_t vert[3];
7467         vec3_t normal;
7468         vec3_t center;
7469         mplane_t plane;
7470         int cam_ent;
7471         r_waterstate_waterplane_t *p;
7472         texture_t *t = R_GetCurrentTexture(surface->texture);
7473         cam_ent = t->camera_entity;
7474         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7475                 cam_ent = 0;
7476
7477         // just use the first triangle with a valid normal for any decisions
7478         VectorClear(normal);
7479         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7480         {
7481                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7482                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7483                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7484                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7485                 if (VectorLength2(normal) >= 0.001)
7486                         break;
7487         }
7488
7489         VectorCopy(normal, plane.normal);
7490         VectorNormalize(plane.normal);
7491         plane.dist = DotProduct(vert[0], plane.normal);
7492         PlaneClassify(&plane);
7493         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7494         {
7495                 // skip backfaces (except if nocullface is set)
7496                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7497                         return;
7498                 VectorNegate(plane.normal, plane.normal);
7499                 plane.dist *= -1;
7500                 PlaneClassify(&plane);
7501         }
7502
7503
7504         // find a matching plane if there is one
7505         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7506                 if(p->camera_entity == t->camera_entity)
7507                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7508                                 break;
7509         if (planeindex >= r_waterstate.maxwaterplanes)
7510                 return; // nothing we can do, out of planes
7511
7512         // if this triangle does not fit any known plane rendered this frame, add one
7513         if (planeindex >= r_waterstate.numwaterplanes)
7514         {
7515                 // store the new plane
7516                 r_waterstate.numwaterplanes++;
7517                 p->plane = plane;
7518                 // clear materialflags and pvs
7519                 p->materialflags = 0;
7520                 p->pvsvalid = false;
7521                 p->camera_entity = t->camera_entity;
7522         }
7523         // merge this surface's materialflags into the waterplane
7524         p->materialflags |= t->currentmaterialflags;
7525         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7526         {
7527                 // merge this surface's PVS into the waterplane
7528                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7529                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7530                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7531                 {
7532                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7533                         p->pvsvalid = true;
7534                 }
7535         }
7536 }
7537
7538 static void R_Water_ProcessPlanes(void)
7539 {
7540         r_refdef_view_t originalview;
7541         r_refdef_view_t myview;
7542         int planeindex;
7543         r_waterstate_waterplane_t *p;
7544         vec3_t visorigin;
7545
7546         originalview = r_refdef.view;
7547
7548         // make sure enough textures are allocated
7549         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7550         {
7551                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7552                 {
7553                         if (!p->texture_refraction)
7554                                 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);
7555                         if (!p->texture_refraction)
7556                                 goto error;
7557                 }
7558                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7559                 {
7560                         if (!p->texture_camera)
7561                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, NULL);
7562                         if (!p->texture_camera)
7563                                 goto error;
7564                 }
7565
7566                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7567                 {
7568                         if (!p->texture_reflection)
7569                                 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);
7570                         if (!p->texture_reflection)
7571                                 goto error;
7572                 }
7573         }
7574
7575         // render views
7576         r_refdef.view = originalview;
7577         r_refdef.view.showdebug = false;
7578         r_refdef.view.width = r_waterstate.waterwidth;
7579         r_refdef.view.height = r_waterstate.waterheight;
7580         r_refdef.view.useclipplane = true;
7581         myview = r_refdef.view;
7582         r_waterstate.renderingscene = true;
7583         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7584         {
7585                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7586                 {
7587                         r_refdef.view = myview;
7588                         // render reflected scene and copy into texture
7589                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7590                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7591                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7592                         r_refdef.view.clipplane = p->plane;
7593                         // reverse the cullface settings for this render
7594                         r_refdef.view.cullface_front = GL_FRONT;
7595                         r_refdef.view.cullface_back = GL_BACK;
7596                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7597                         {
7598                                 r_refdef.view.usecustompvs = true;
7599                                 if (p->pvsvalid)
7600                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7601                                 else
7602                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7603                         }
7604
7605                         R_ResetViewRendering3D();
7606                         R_ClearScreen(r_refdef.fogenabled);
7607                         R_View_Update();
7608                         R_RenderScene();
7609
7610                         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);
7611                 }
7612
7613                 // render the normal view scene and copy into texture
7614                 // (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)
7615                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7616                 {
7617                         r_waterstate.renderingrefraction = true;
7618                         r_refdef.view = myview;
7619
7620                         r_refdef.view.clipplane = p->plane;
7621                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7622                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7623
7624                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7625                         {
7626                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7627                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7628                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7629                                 R_RenderView_UpdateViewVectors();
7630                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7631                         }
7632
7633                         PlaneClassify(&r_refdef.view.clipplane);
7634
7635                         R_ResetViewRendering3D();
7636                         R_ClearScreen(r_refdef.fogenabled);
7637                         R_View_Update();
7638                         R_RenderScene();
7639
7640                         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);
7641                         r_waterstate.renderingrefraction = false;
7642                 }
7643                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7644                 {
7645                         r_refdef.view = myview;
7646
7647                         r_refdef.view.clipplane = p->plane;
7648                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7649                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7650
7651                         r_refdef.view.width = r_waterstate.camerawidth;
7652                         r_refdef.view.height = r_waterstate.cameraheight;
7653                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7654                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7655
7656                         if(p->camera_entity)
7657                         {
7658                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7659                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7660                         }
7661
7662                         // reverse the cullface settings for this render
7663                         r_refdef.view.cullface_front = GL_FRONT;
7664                         r_refdef.view.cullface_back = GL_BACK;
7665                         // also reverse the view matrix
7666                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, -1, 1);
7667                         R_RenderView_UpdateViewVectors();
7668                         if(p->camera_entity)
7669                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
7670                         
7671                         // camera needs no clipplane
7672                         r_refdef.view.useclipplane = false;
7673
7674                         PlaneClassify(&r_refdef.view.clipplane);
7675
7676                         R_ResetViewRendering3D();
7677                         R_ClearScreen(r_refdef.fogenabled);
7678                         R_View_Update();
7679                         R_RenderScene();
7680
7681                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7682                         r_waterstate.renderingrefraction = false;
7683                 }
7684
7685         }
7686         r_waterstate.renderingscene = false;
7687         r_refdef.view = originalview;
7688         R_ResetViewRendering3D();
7689         R_ClearScreen(r_refdef.fogenabled);
7690         R_View_Update();
7691         return;
7692 error:
7693         r_refdef.view = originalview;
7694         r_waterstate.renderingscene = false;
7695         Cvar_SetValueQuick(&r_water, 0);
7696         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7697         return;
7698 }
7699
7700 void R_Bloom_StartFrame(void)
7701 {
7702         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7703
7704         switch(vid.renderpath)
7705         {
7706         case RENDERPATH_GL20:
7707         case RENDERPATH_CGGL:
7708                 break;
7709         case RENDERPATH_GL13:
7710         case RENDERPATH_GL11:
7711                 return;
7712         }
7713
7714         // set bloomwidth and bloomheight to the bloom resolution that will be
7715         // used (often less than the screen resolution for faster rendering)
7716         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7717         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7718         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7719         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7720         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7721
7722         // calculate desired texture sizes
7723         if (vid.support.arb_texture_non_power_of_two)
7724         {
7725                 screentexturewidth = r_refdef.view.width;
7726                 screentextureheight = r_refdef.view.height;
7727                 bloomtexturewidth = r_bloomstate.bloomwidth;
7728                 bloomtextureheight = r_bloomstate.bloomheight;
7729         }
7730         else
7731         {
7732                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7733                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7734                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7735                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7736         }
7737
7738         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))
7739         {
7740                 Cvar_SetValueQuick(&r_hdr, 0);
7741                 Cvar_SetValueQuick(&r_bloom, 0);
7742                 Cvar_SetValueQuick(&r_motionblur, 0);
7743                 Cvar_SetValueQuick(&r_damageblur, 0);
7744         }
7745
7746         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)))
7747                 screentexturewidth = screentextureheight = 0;
7748         if (!r_hdr.integer && !r_bloom.integer)
7749                 bloomtexturewidth = bloomtextureheight = 0;
7750
7751         // allocate textures as needed
7752         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7753         {
7754                 if (r_bloomstate.texture_screen)
7755                         R_FreeTexture(r_bloomstate.texture_screen);
7756                 r_bloomstate.texture_screen = NULL;
7757                 r_bloomstate.screentexturewidth = screentexturewidth;
7758                 r_bloomstate.screentextureheight = screentextureheight;
7759                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7760                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, NULL);
7761         }
7762         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7763         {
7764                 if (r_bloomstate.texture_bloom)
7765                         R_FreeTexture(r_bloomstate.texture_bloom);
7766                 r_bloomstate.texture_bloom = NULL;
7767                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7768                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7769                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7770                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
7771         }
7772
7773         // when doing a reduced render (HDR) we want to use a smaller area
7774         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7775         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7776         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7777         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7778         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7779
7780         // set up a texcoord array for the full resolution screen image
7781         // (we have to keep this around to copy back during final render)
7782         r_bloomstate.screentexcoord2f[0] = 0;
7783         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7784         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7785         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7786         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7787         r_bloomstate.screentexcoord2f[5] = 0;
7788         r_bloomstate.screentexcoord2f[6] = 0;
7789         r_bloomstate.screentexcoord2f[7] = 0;
7790
7791         // set up a texcoord array for the reduced resolution bloom image
7792         // (which will be additive blended over the screen image)
7793         r_bloomstate.bloomtexcoord2f[0] = 0;
7794         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7795         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7796         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7797         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7798         r_bloomstate.bloomtexcoord2f[5] = 0;
7799         r_bloomstate.bloomtexcoord2f[6] = 0;
7800         r_bloomstate.bloomtexcoord2f[7] = 0;
7801
7802         if (r_hdr.integer || r_bloom.integer)
7803         {
7804                 r_bloomstate.enabled = true;
7805                 r_bloomstate.hdr = r_hdr.integer != 0;
7806         }
7807
7808         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);
7809 }
7810
7811 void R_Bloom_CopyBloomTexture(float colorscale)
7812 {
7813         r_refdef.stats.bloom++;
7814
7815         // scale down screen texture to the bloom texture size
7816         CHECKGLERROR
7817         R_SetViewport(&r_bloomstate.viewport);
7818         GL_BlendFunc(GL_ONE, GL_ZERO);
7819         GL_Color(colorscale, colorscale, colorscale, 1);
7820         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
7821         // TODO: do boxfilter scale-down in shader?
7822         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7823         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7824         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7825
7826         // we now have a bloom image in the framebuffer
7827         // copy it into the bloom image texture for later processing
7828         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);
7829         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7830 }
7831
7832 void R_Bloom_CopyHDRTexture(void)
7833 {
7834         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);
7835         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7836 }
7837
7838 void R_Bloom_MakeTexture(void)
7839 {
7840         int x, range, dir;
7841         float xoffset, yoffset, r, brighten;
7842
7843         r_refdef.stats.bloom++;
7844
7845         R_ResetViewRendering2D();
7846
7847         // we have a bloom image in the framebuffer
7848         CHECKGLERROR
7849         R_SetViewport(&r_bloomstate.viewport);
7850
7851         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7852         {
7853                 x *= 2;
7854                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7855                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7856                 GL_Color(r,r,r,1);
7857                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7858                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7859                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7860                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7861
7862                 // copy the vertically blurred bloom view to a texture
7863                 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);
7864                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7865         }
7866
7867         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7868         brighten = r_bloom_brighten.value;
7869         if (r_hdr.integer)
7870                 brighten *= r_hdr_range.value;
7871         brighten = sqrt(brighten);
7872         if(range >= 1)
7873                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7874         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7875
7876         for (dir = 0;dir < 2;dir++)
7877         {
7878                 // blend on at multiple vertical offsets to achieve a vertical blur
7879                 // TODO: do offset blends using GLSL
7880                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7881                 GL_BlendFunc(GL_ONE, GL_ZERO);
7882                 for (x = -range;x <= range;x++)
7883                 {
7884                         if (!dir){xoffset = 0;yoffset = x;}
7885                         else {xoffset = x;yoffset = 0;}
7886                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7887                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7888                         // compute a texcoord array with the specified x and y offset
7889                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7890                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7891                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7892                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7893                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7894                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7895                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7896                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7897                         // this r value looks like a 'dot' particle, fading sharply to
7898                         // black at the edges
7899                         // (probably not realistic but looks good enough)
7900                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7901                         //r = brighten/(range*2+1);
7902                         r = brighten / (range * 2 + 1);
7903                         if(range >= 1)
7904                                 r *= (1 - x*x/(float)(range*range));
7905                         GL_Color(r, r, r, 1);
7906                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
7907                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7908                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7909                         GL_BlendFunc(GL_ONE, GL_ONE);
7910                 }
7911
7912                 // copy the vertically blurred bloom view to a texture
7913                 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);
7914                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7915         }
7916
7917         // apply subtract last
7918         // (just like it would be in a GLSL shader)
7919         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7920         {
7921                 GL_BlendFunc(GL_ONE, GL_ZERO);
7922                 GL_Color(1,1,1,1);
7923                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7924                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7925                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7926                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7927
7928                 GL_BlendFunc(GL_ONE, GL_ONE);
7929                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7930                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7931                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7932                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7933                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7934                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7935                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7936
7937                 // copy the darkened bloom view to a texture
7938                 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);
7939                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7940         }
7941 }
7942
7943 void R_HDR_RenderBloomTexture(void)
7944 {
7945         int oldwidth, oldheight;
7946         float oldcolorscale;
7947
7948         oldcolorscale = r_refdef.view.colorscale;
7949         oldwidth = r_refdef.view.width;
7950         oldheight = r_refdef.view.height;
7951         r_refdef.view.width = r_bloomstate.bloomwidth;
7952         r_refdef.view.height = r_bloomstate.bloomheight;
7953
7954         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7955         // TODO: add exposure compensation features
7956         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7957
7958         r_refdef.view.showdebug = false;
7959         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
7960
7961         R_ResetViewRendering3D();
7962
7963         R_ClearScreen(r_refdef.fogenabled);
7964         if (r_timereport_active)
7965                 R_TimeReport("HDRclear");
7966
7967         R_View_Update();
7968         if (r_timereport_active)
7969                 R_TimeReport("visibility");
7970
7971         // only do secondary renders with HDR if r_hdr is 2 or higher
7972         r_waterstate.numwaterplanes = 0;
7973         if (r_waterstate.enabled && r_hdr.integer >= 2)
7974                 R_RenderWaterPlanes();
7975
7976         r_refdef.view.showdebug = true;
7977         R_RenderScene();
7978         r_waterstate.numwaterplanes = 0;
7979
7980         R_ResetViewRendering2D();
7981
7982         R_Bloom_CopyHDRTexture();
7983         R_Bloom_MakeTexture();
7984
7985         // restore the view settings
7986         r_refdef.view.width = oldwidth;
7987         r_refdef.view.height = oldheight;
7988         r_refdef.view.colorscale = oldcolorscale;
7989
7990         R_ResetViewRendering3D();
7991
7992         R_ClearScreen(r_refdef.fogenabled);
7993         if (r_timereport_active)
7994                 R_TimeReport("viewclear");
7995 }
7996
7997 static void R_BlendView(void)
7998 {
7999         unsigned int permutation;
8000         float uservecs[4][4];
8001
8002         switch (vid.renderpath)
8003         {
8004         case RENDERPATH_GL20:
8005         case RENDERPATH_CGGL:
8006                 permutation =
8007                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8008                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8009                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8010                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8011                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8012
8013                 if (r_bloomstate.texture_screen)
8014                 {
8015                         // make sure the buffer is available
8016                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8017
8018                         R_ResetViewRendering2D();
8019
8020                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8021                         {
8022                                 // declare variables
8023                                 float speed;
8024                                 static float avgspeed;
8025
8026                                 speed = VectorLength(cl.movement_velocity);
8027
8028                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8029                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8030
8031                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8032                                 speed = bound(0, speed, 1);
8033                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8034
8035                                 // calculate values into a standard alpha
8036                                 cl.motionbluralpha = 1 - exp(-
8037                                                 (
8038                                                  (r_motionblur.value * speed / 80)
8039                                                  +
8040                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8041                                                 )
8042                                                 /
8043                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8044                                            );
8045
8046                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8047                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8048                                 // apply the blur
8049                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8050                                 {
8051                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8052                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8053                                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8054                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8055                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8056                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8057                                 }
8058                         }
8059
8060                         // copy view into the screen texture
8061                         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);
8062                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8063                 }
8064                 else if (!r_bloomstate.texture_bloom)
8065                 {
8066                         // we may still have to do view tint...
8067                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8068                         {
8069                                 // apply a color tint to the whole view
8070                                 R_ResetViewRendering2D();
8071                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8072                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8073                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8074                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8075                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8076                         }
8077                         break; // no screen processing, no bloom, skip it
8078                 }
8079
8080                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8081                 {
8082                         // render simple bloom effect
8083                         // copy the screen and shrink it and darken it for the bloom process
8084                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8085                         // make the bloom texture
8086                         R_Bloom_MakeTexture();
8087                 }
8088
8089 #if _MSC_VER >= 1400
8090 #define sscanf sscanf_s
8091 #endif
8092                 memset(uservecs, 0, sizeof(uservecs));
8093                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8094                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8095                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8096                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8097
8098                 R_ResetViewRendering2D();
8099                 GL_Color(1, 1, 1, 1);
8100                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8101                 GL_BlendFunc(GL_ONE, GL_ZERO);
8102
8103                 switch(vid.renderpath)
8104                 {
8105                 case RENDERPATH_GL20:
8106                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8107                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8108                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8109                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8110                         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]);
8111                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8112                         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]);
8113                         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]);
8114                         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]);
8115                         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]);
8116                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8117                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8118                         break;
8119                 case RENDERPATH_CGGL:
8120 #ifdef SUPPORTCG
8121                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8122                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8123                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8124                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8125                         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
8126                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8127                         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
8128                         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
8129                         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
8130                         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
8131                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8132                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8133 #endif
8134                         break;
8135                 default:
8136                         break;
8137                 }
8138                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8139                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8140                 break;
8141         case RENDERPATH_GL13:
8142         case RENDERPATH_GL11:
8143                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8144                 {
8145                         // apply a color tint to the whole view
8146                         R_ResetViewRendering2D();
8147                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8148                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8149                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8150                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8151                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8152                 }
8153                 break;
8154         }
8155 }
8156
8157 matrix4x4_t r_waterscrollmatrix;
8158
8159 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8160 {
8161         if (r_refdef.fog_density)
8162         {
8163                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8164                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8165                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8166
8167                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8168                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8169                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8170                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8171
8172                 {
8173                         vec3_t fogvec;
8174                         VectorCopy(r_refdef.fogcolor, fogvec);
8175                         //   color.rgb *= ContrastBoost * SceneBrightness;
8176                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8177                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8178                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8179                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8180                 }
8181         }
8182 }
8183
8184 void R_UpdateVariables(void)
8185 {
8186         R_Textures_Frame();
8187
8188         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8189
8190         r_refdef.farclip = r_farclip_base.value;
8191         if (r_refdef.scene.worldmodel)
8192                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8193         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8194
8195         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8196                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8197         r_refdef.polygonfactor = 0;
8198         r_refdef.polygonoffset = 0;
8199         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8200         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8201
8202         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8203         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8204         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8205         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8206         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8207         if (r_showsurfaces.integer)
8208         {
8209                 r_refdef.scene.rtworld = false;
8210                 r_refdef.scene.rtworldshadows = false;
8211                 r_refdef.scene.rtdlight = false;
8212                 r_refdef.scene.rtdlightshadows = false;
8213                 r_refdef.lightmapintensity = 0;
8214         }
8215
8216         if (gamemode == GAME_NEHAHRA)
8217         {
8218                 if (gl_fogenable.integer)
8219                 {
8220                         r_refdef.oldgl_fogenable = true;
8221                         r_refdef.fog_density = gl_fogdensity.value;
8222                         r_refdef.fog_red = gl_fogred.value;
8223                         r_refdef.fog_green = gl_foggreen.value;
8224                         r_refdef.fog_blue = gl_fogblue.value;
8225                         r_refdef.fog_alpha = 1;
8226                         r_refdef.fog_start = 0;
8227                         r_refdef.fog_end = gl_skyclip.value;
8228                         r_refdef.fog_height = 1<<30;
8229                         r_refdef.fog_fadedepth = 128;
8230                 }
8231                 else if (r_refdef.oldgl_fogenable)
8232                 {
8233                         r_refdef.oldgl_fogenable = false;
8234                         r_refdef.fog_density = 0;
8235                         r_refdef.fog_red = 0;
8236                         r_refdef.fog_green = 0;
8237                         r_refdef.fog_blue = 0;
8238                         r_refdef.fog_alpha = 0;
8239                         r_refdef.fog_start = 0;
8240                         r_refdef.fog_end = 0;
8241                         r_refdef.fog_height = 1<<30;
8242                         r_refdef.fog_fadedepth = 128;
8243                 }
8244         }
8245
8246         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8247         r_refdef.fog_start = max(0, r_refdef.fog_start);
8248         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8249
8250         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8251
8252         if (r_refdef.fog_density && r_drawfog.integer)
8253         {
8254                 r_refdef.fogenabled = true;
8255                 // this is the point where the fog reaches 0.9986 alpha, which we
8256                 // consider a good enough cutoff point for the texture
8257                 // (0.9986 * 256 == 255.6)
8258                 if (r_fog_exp2.integer)
8259                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8260                 else
8261                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8262                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8263                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8264                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8265                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8266                         R_BuildFogHeightTexture();
8267                 // fog color was already set
8268                 // update the fog texture
8269                 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)
8270                         R_BuildFogTexture();
8271                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8272                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8273         }
8274         else
8275                 r_refdef.fogenabled = false;
8276
8277         switch(vid.renderpath)
8278         {
8279         case RENDERPATH_GL20:
8280         case RENDERPATH_CGGL:
8281                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8282                 {
8283                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8284                         {
8285                                 // build GLSL gamma texture
8286 #define RAMPWIDTH 256
8287                                 unsigned short ramp[RAMPWIDTH * 3];
8288                                 unsigned char rampbgr[RAMPWIDTH][4];
8289                                 int i;
8290
8291                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8292
8293                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8294                                 for(i = 0; i < RAMPWIDTH; ++i)
8295                                 {
8296                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8297                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8298                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8299                                         rampbgr[i][3] = 0;
8300                                 }
8301                                 if (r_texture_gammaramps)
8302                                 {
8303                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8304                                 }
8305                                 else
8306                                 {
8307                                         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);
8308                                 }
8309                         }
8310                 }
8311                 else
8312                 {
8313                         // remove GLSL gamma texture
8314                 }
8315                 break;
8316         case RENDERPATH_GL13:
8317         case RENDERPATH_GL11:
8318                 break;
8319         }
8320 }
8321
8322 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8323 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8324 /*
8325 ================
8326 R_SelectScene
8327 ================
8328 */
8329 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8330         if( scenetype != r_currentscenetype ) {
8331                 // store the old scenetype
8332                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8333                 r_currentscenetype = scenetype;
8334                 // move in the new scene
8335                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8336         }
8337 }
8338
8339 /*
8340 ================
8341 R_GetScenePointer
8342 ================
8343 */
8344 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8345 {
8346         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8347         if( scenetype == r_currentscenetype ) {
8348                 return &r_refdef.scene;
8349         } else {
8350                 return &r_scenes_store[ scenetype ];
8351         }
8352 }
8353
8354 /*
8355 ================
8356 R_RenderView
8357 ================
8358 */
8359 void R_RenderView(void)
8360 {
8361         if (r_timereport_active)
8362                 R_TimeReport("start");
8363         r_textureframe++; // used only by R_GetCurrentTexture
8364         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8365
8366         if (!r_drawentities.integer)
8367                 r_refdef.scene.numentities = 0;
8368
8369         R_AnimCache_ClearCache();
8370         R_FrameData_NewFrame();
8371
8372         if (r_refdef.view.isoverlay)
8373         {
8374                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8375                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8376                 R_TimeReport("depthclear");
8377
8378                 r_refdef.view.showdebug = false;
8379
8380                 r_waterstate.enabled = false;
8381                 r_waterstate.numwaterplanes = 0;
8382
8383                 R_RenderScene();
8384
8385                 CHECKGLERROR
8386                 return;
8387         }
8388
8389         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8390                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8391
8392         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8393
8394         R_RenderView_UpdateViewVectors();
8395
8396         R_Shadow_UpdateWorldLightSelection();
8397
8398         R_Bloom_StartFrame();
8399         R_Water_StartFrame();
8400
8401         CHECKGLERROR
8402         if (r_timereport_active)
8403                 R_TimeReport("viewsetup");
8404
8405         R_ResetViewRendering3D();
8406
8407         if (r_refdef.view.clear || r_refdef.fogenabled)
8408         {
8409                 R_ClearScreen(r_refdef.fogenabled);
8410                 if (r_timereport_active)
8411                         R_TimeReport("viewclear");
8412         }
8413         r_refdef.view.clear = true;
8414
8415         // this produces a bloom texture to be used in R_BlendView() later
8416         if (r_hdr.integer && r_bloomstate.bloomwidth)
8417         {
8418                 R_HDR_RenderBloomTexture();
8419                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8420                 r_textureframe++; // used only by R_GetCurrentTexture
8421         }
8422
8423         r_refdef.view.showdebug = true;
8424
8425         R_View_Update();
8426         if (r_timereport_active)
8427                 R_TimeReport("visibility");
8428
8429         r_waterstate.numwaterplanes = 0;
8430         if (r_waterstate.enabled)
8431                 R_RenderWaterPlanes();
8432
8433         R_RenderScene();
8434         r_waterstate.numwaterplanes = 0;
8435
8436         R_BlendView();
8437         if (r_timereport_active)
8438                 R_TimeReport("blendview");
8439
8440         GL_Scissor(0, 0, vid.width, vid.height);
8441         GL_ScissorTest(false);
8442         CHECKGLERROR
8443 }
8444
8445 void R_RenderWaterPlanes(void)
8446 {
8447         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8448         {
8449                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8450                 if (r_timereport_active)
8451                         R_TimeReport("waterworld");
8452         }
8453
8454         // don't let sound skip if going slow
8455         if (r_refdef.scene.extraupdate)
8456                 S_ExtraUpdate ();
8457
8458         R_DrawModelsAddWaterPlanes();
8459         if (r_timereport_active)
8460                 R_TimeReport("watermodels");
8461
8462         if (r_waterstate.numwaterplanes)
8463         {
8464                 R_Water_ProcessPlanes();
8465                 if (r_timereport_active)
8466                         R_TimeReport("waterscenes");
8467         }
8468 }
8469
8470 extern void R_DrawLightningBeams (void);
8471 extern void VM_CL_AddPolygonsToMeshQueue (void);
8472 extern void R_DrawPortals (void);
8473 extern cvar_t cl_locs_show;
8474 static void R_DrawLocs(void);
8475 static void R_DrawEntityBBoxes(void);
8476 static void R_DrawModelDecals(void);
8477 extern void R_DrawModelShadows(void);
8478 extern void R_DrawModelShadowMaps(void);
8479 extern cvar_t cl_decals_newsystem;
8480 extern qboolean r_shadow_usingdeferredprepass;
8481 void R_RenderScene(void)
8482 {
8483         qboolean shadowmapping = false;
8484
8485         if (r_timereport_active)
8486                 R_TimeReport("beginscene");
8487
8488         r_refdef.stats.renders++;
8489
8490         R_UpdateFogColor();
8491
8492         // don't let sound skip if going slow
8493         if (r_refdef.scene.extraupdate)
8494                 S_ExtraUpdate ();
8495
8496         R_MeshQueue_BeginScene();
8497
8498         R_SkyStartFrame();
8499
8500         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);
8501
8502         if (r_timereport_active)
8503                 R_TimeReport("skystartframe");
8504
8505         if (cl.csqc_vidvars.drawworld)
8506         {
8507                 // don't let sound skip if going slow
8508                 if (r_refdef.scene.extraupdate)
8509                         S_ExtraUpdate ();
8510
8511                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8512                 {
8513                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8514                         if (r_timereport_active)
8515                                 R_TimeReport("worldsky");
8516                 }
8517
8518                 if (R_DrawBrushModelsSky() && r_timereport_active)
8519                         R_TimeReport("bmodelsky");
8520
8521                 if (skyrendermasked && skyrenderlater)
8522                 {
8523                         // we have to force off the water clipping plane while rendering sky
8524                         R_SetupView(false);
8525                         R_Sky();
8526                         R_SetupView(true);
8527                         if (r_timereport_active)
8528                                 R_TimeReport("sky");
8529                 }
8530         }
8531
8532         R_AnimCache_CacheVisibleEntities();
8533         if (r_timereport_active)
8534                 R_TimeReport("animation");
8535
8536         R_Shadow_PrepareLights();
8537         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8538                 R_Shadow_PrepareModelShadows();
8539         if (r_timereport_active)
8540                 R_TimeReport("preparelights");
8541
8542         if (R_Shadow_ShadowMappingEnabled())
8543                 shadowmapping = true;
8544
8545         if (r_shadow_usingdeferredprepass)
8546                 R_Shadow_DrawPrepass();
8547
8548         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8549         {
8550                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8551                 if (r_timereport_active)
8552                         R_TimeReport("worlddepth");
8553         }
8554         if (r_depthfirst.integer >= 2)
8555         {
8556                 R_DrawModelsDepth();
8557                 if (r_timereport_active)
8558                         R_TimeReport("modeldepth");
8559         }
8560
8561         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8562         {
8563                 R_DrawModelShadowMaps();
8564                 R_ResetViewRendering3D();
8565                 // don't let sound skip if going slow
8566                 if (r_refdef.scene.extraupdate)
8567                         S_ExtraUpdate ();
8568         }
8569
8570         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8571         {
8572                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8573                 if (r_timereport_active)
8574                         R_TimeReport("world");
8575         }
8576
8577         // don't let sound skip if going slow
8578         if (r_refdef.scene.extraupdate)
8579                 S_ExtraUpdate ();
8580
8581         R_DrawModels();
8582         if (r_timereport_active)
8583                 R_TimeReport("models");
8584
8585         // don't let sound skip if going slow
8586         if (r_refdef.scene.extraupdate)
8587                 S_ExtraUpdate ();
8588
8589         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8590         {
8591                 R_DrawModelShadows();
8592                 R_ResetViewRendering3D();
8593                 // don't let sound skip if going slow
8594                 if (r_refdef.scene.extraupdate)
8595                         S_ExtraUpdate ();
8596         }
8597
8598         if (!r_shadow_usingdeferredprepass)
8599         {
8600                 R_Shadow_DrawLights();
8601                 if (r_timereport_active)
8602                         R_TimeReport("rtlights");
8603         }
8604
8605         // don't let sound skip if going slow
8606         if (r_refdef.scene.extraupdate)
8607                 S_ExtraUpdate ();
8608
8609         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8610         {
8611                 R_DrawModelShadows();
8612                 R_ResetViewRendering3D();
8613                 // don't let sound skip if going slow
8614                 if (r_refdef.scene.extraupdate)
8615                         S_ExtraUpdate ();
8616         }
8617
8618         if (cl.csqc_vidvars.drawworld)
8619         {
8620                 if (cl_decals_newsystem.integer)
8621                 {
8622                         R_DrawModelDecals();
8623                         if (r_timereport_active)
8624                                 R_TimeReport("modeldecals");
8625                 }
8626                 else
8627                 {
8628                         R_DrawDecals();
8629                         if (r_timereport_active)
8630                                 R_TimeReport("decals");
8631                 }
8632
8633                 R_DrawParticles();
8634                 if (r_timereport_active)
8635                         R_TimeReport("particles");
8636
8637                 R_DrawExplosions();
8638                 if (r_timereport_active)
8639                         R_TimeReport("explosions");
8640
8641                 R_DrawLightningBeams();
8642                 if (r_timereport_active)
8643                         R_TimeReport("lightning");
8644         }
8645
8646         VM_CL_AddPolygonsToMeshQueue();
8647
8648         if (r_refdef.view.showdebug)
8649         {
8650                 if (cl_locs_show.integer)
8651                 {
8652                         R_DrawLocs();
8653                         if (r_timereport_active)
8654                                 R_TimeReport("showlocs");
8655                 }
8656
8657                 if (r_drawportals.integer)
8658                 {
8659                         R_DrawPortals();
8660                         if (r_timereport_active)
8661                                 R_TimeReport("portals");
8662                 }
8663
8664                 if (r_showbboxes.value > 0)
8665                 {
8666                         R_DrawEntityBBoxes();
8667                         if (r_timereport_active)
8668                                 R_TimeReport("bboxes");
8669                 }
8670         }
8671
8672         R_MeshQueue_RenderTransparent();
8673         if (r_timereport_active)
8674                 R_TimeReport("drawtrans");
8675
8676         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))
8677         {
8678                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8679                 if (r_timereport_active)
8680                         R_TimeReport("worlddebug");
8681                 R_DrawModelsDebug();
8682                 if (r_timereport_active)
8683                         R_TimeReport("modeldebug");
8684         }
8685
8686         if (cl.csqc_vidvars.drawworld)
8687         {
8688                 R_Shadow_DrawCoronas();
8689                 if (r_timereport_active)
8690                         R_TimeReport("coronas");
8691         }
8692
8693         // don't let sound skip if going slow
8694         if (r_refdef.scene.extraupdate)
8695                 S_ExtraUpdate ();
8696
8697         R_ResetViewRendering2D();
8698 }
8699
8700 static const unsigned short bboxelements[36] =
8701 {
8702         5, 1, 3, 5, 3, 7,
8703         6, 2, 0, 6, 0, 4,
8704         7, 3, 2, 7, 2, 6,
8705         4, 0, 1, 4, 1, 5,
8706         4, 5, 7, 4, 7, 6,
8707         1, 0, 2, 1, 2, 3,
8708 };
8709
8710 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8711 {
8712         int i;
8713         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8714
8715         RSurf_ActiveWorldEntity();
8716
8717         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8718         GL_DepthMask(false);
8719         GL_DepthRange(0, 1);
8720         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8721         R_Mesh_ResetTextureState();
8722
8723         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8724         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8725         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8726         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8727         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8728         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8729         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8730         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8731         R_FillColors(color4f, 8, cr, cg, cb, ca);
8732         if (r_refdef.fogenabled)
8733         {
8734                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8735                 {
8736                         f1 = RSurf_FogVertex(v);
8737                         f2 = 1 - f1;
8738                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8739                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8740                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8741                 }
8742         }
8743         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
8744         R_Mesh_ResetTextureState();
8745         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8746         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
8747 }
8748
8749 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8750 {
8751         int i;
8752         float color[4];
8753         prvm_edict_t *edict;
8754         prvm_prog_t *prog_save = prog;
8755
8756         // this function draws bounding boxes of server entities
8757         if (!sv.active)
8758                 return;
8759
8760         GL_CullFace(GL_NONE);
8761         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8762
8763         prog = 0;
8764         SV_VM_Begin();
8765         for (i = 0;i < numsurfaces;i++)
8766         {
8767                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8768                 switch ((int)edict->fields.server->solid)
8769                 {
8770                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8771                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8772                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8773                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8774                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8775                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8776                 }
8777                 color[3] *= r_showbboxes.value;
8778                 color[3] = bound(0, color[3], 1);
8779                 GL_DepthTest(!r_showdisabledepthtest.integer);
8780                 GL_CullFace(r_refdef.view.cullface_front);
8781                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8782         }
8783         SV_VM_End();
8784         prog = prog_save;
8785 }
8786
8787 static void R_DrawEntityBBoxes(void)
8788 {
8789         int i;
8790         prvm_edict_t *edict;
8791         vec3_t center;
8792         prvm_prog_t *prog_save = prog;
8793
8794         // this function draws bounding boxes of server entities
8795         if (!sv.active)
8796                 return;
8797
8798         prog = 0;
8799         SV_VM_Begin();
8800         for (i = 0;i < prog->num_edicts;i++)
8801         {
8802                 edict = PRVM_EDICT_NUM(i);
8803                 if (edict->priv.server->free)
8804                         continue;
8805                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8806                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8807                         continue;
8808                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8809                         continue;
8810                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8811                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8812         }
8813         SV_VM_End();
8814         prog = prog_save;
8815 }
8816
8817 static const int nomodelelement3i[24] =
8818 {
8819         5, 2, 0,
8820         5, 1, 2,
8821         5, 0, 3,
8822         5, 3, 1,
8823         0, 2, 4,
8824         2, 1, 4,
8825         3, 0, 4,
8826         1, 3, 4
8827 };
8828
8829 static const unsigned short nomodelelement3s[24] =
8830 {
8831         5, 2, 0,
8832         5, 1, 2,
8833         5, 0, 3,
8834         5, 3, 1,
8835         0, 2, 4,
8836         2, 1, 4,
8837         3, 0, 4,
8838         1, 3, 4
8839 };
8840
8841 static const float nomodelvertex3f[6*3] =
8842 {
8843         -16,   0,   0,
8844          16,   0,   0,
8845           0, -16,   0,
8846           0,  16,   0,
8847           0,   0, -16,
8848           0,   0,  16
8849 };
8850
8851 static const float nomodelcolor4f[6*4] =
8852 {
8853         0.0f, 0.0f, 0.5f, 1.0f,
8854         0.0f, 0.0f, 0.5f, 1.0f,
8855         0.0f, 0.5f, 0.0f, 1.0f,
8856         0.0f, 0.5f, 0.0f, 1.0f,
8857         0.5f, 0.0f, 0.0f, 1.0f,
8858         0.5f, 0.0f, 0.0f, 1.0f
8859 };
8860
8861 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8862 {
8863         int i;
8864         float f1, f2, *c;
8865         float color4f[6*4];
8866
8867         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);
8868
8869         // this is only called once per entity so numsurfaces is always 1, and
8870         // surfacelist is always {0}, so this code does not handle batches
8871
8872         if (rsurface.ent_flags & RENDER_ADDITIVE)
8873         {
8874                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8875                 GL_DepthMask(false);
8876         }
8877         else if (rsurface.colormod[3] < 1)
8878         {
8879                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8880                 GL_DepthMask(false);
8881         }
8882         else
8883         {
8884                 GL_BlendFunc(GL_ONE, GL_ZERO);
8885                 GL_DepthMask(true);
8886         }
8887         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8888         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8889         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8890         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8891         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8892         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8893         for (i = 0, c = color4f;i < 6;i++, c += 4)
8894         {
8895                 c[0] *= rsurface.colormod[0];
8896                 c[1] *= rsurface.colormod[1];
8897                 c[2] *= rsurface.colormod[2];
8898                 c[3] *= rsurface.colormod[3];
8899         }
8900         if (r_refdef.fogenabled)
8901         {
8902                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8903                 {
8904                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
8905                         f2 = 1 - f1;
8906                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8907                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8908                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8909                 }
8910         }
8911         R_Mesh_ResetTextureState();
8912         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8913         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8914 }
8915
8916 void R_DrawNoModel(entity_render_t *ent)
8917 {
8918         vec3_t org;
8919         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8920         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8921                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8922         else
8923                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8924 }
8925
8926 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8927 {
8928         vec3_t right1, right2, diff, normal;
8929
8930         VectorSubtract (org2, org1, normal);
8931
8932         // calculate 'right' vector for start
8933         VectorSubtract (r_refdef.view.origin, org1, diff);
8934         CrossProduct (normal, diff, right1);
8935         VectorNormalize (right1);
8936
8937         // calculate 'right' vector for end
8938         VectorSubtract (r_refdef.view.origin, org2, diff);
8939         CrossProduct (normal, diff, right2);
8940         VectorNormalize (right2);
8941
8942         vert[ 0] = org1[0] + width * right1[0];
8943         vert[ 1] = org1[1] + width * right1[1];
8944         vert[ 2] = org1[2] + width * right1[2];
8945         vert[ 3] = org1[0] - width * right1[0];
8946         vert[ 4] = org1[1] - width * right1[1];
8947         vert[ 5] = org1[2] - width * right1[2];
8948         vert[ 6] = org2[0] - width * right2[0];
8949         vert[ 7] = org2[1] - width * right2[1];
8950         vert[ 8] = org2[2] - width * right2[2];
8951         vert[ 9] = org2[0] + width * right2[0];
8952         vert[10] = org2[1] + width * right2[1];
8953         vert[11] = org2[2] + width * right2[2];
8954 }
8955
8956 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)
8957 {
8958         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8959         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8960         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8961         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8962         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8963         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8964         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8965         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8966         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8967         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8968         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8969         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8970 }
8971
8972 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8973 {
8974         int i;
8975         float *vertex3f;
8976         float v[3];
8977         VectorSet(v, x, y, z);
8978         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8979                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8980                         break;
8981         if (i == mesh->numvertices)
8982         {
8983                 if (mesh->numvertices < mesh->maxvertices)
8984                 {
8985                         VectorCopy(v, vertex3f);
8986                         mesh->numvertices++;
8987                 }
8988                 return mesh->numvertices;
8989         }
8990         else
8991                 return i;
8992 }
8993
8994 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8995 {
8996         int i;
8997         int *e, element[3];
8998         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8999         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9000         e = mesh->element3i + mesh->numtriangles * 3;
9001         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9002         {
9003                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9004                 if (mesh->numtriangles < mesh->maxtriangles)
9005                 {
9006                         *e++ = element[0];
9007                         *e++ = element[1];
9008                         *e++ = element[2];
9009                         mesh->numtriangles++;
9010                 }
9011                 element[1] = element[2];
9012         }
9013 }
9014
9015 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9016 {
9017         int i;
9018         int *e, element[3];
9019         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9020         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9021         e = mesh->element3i + mesh->numtriangles * 3;
9022         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9023         {
9024                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9025                 if (mesh->numtriangles < mesh->maxtriangles)
9026                 {
9027                         *e++ = element[0];
9028                         *e++ = element[1];
9029                         *e++ = element[2];
9030                         mesh->numtriangles++;
9031                 }
9032                 element[1] = element[2];
9033         }
9034 }
9035
9036 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9037 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9038 {
9039         int planenum, planenum2;
9040         int w;
9041         int tempnumpoints;
9042         mplane_t *plane, *plane2;
9043         double maxdist;
9044         double temppoints[2][256*3];
9045         // figure out how large a bounding box we need to properly compute this brush
9046         maxdist = 0;
9047         for (w = 0;w < numplanes;w++)
9048                 maxdist = max(maxdist, fabs(planes[w].dist));
9049         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9050         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9051         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9052         {
9053                 w = 0;
9054                 tempnumpoints = 4;
9055                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9056                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9057                 {
9058                         if (planenum2 == planenum)
9059                                 continue;
9060                         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);
9061                         w = !w;
9062                 }
9063                 if (tempnumpoints < 3)
9064                         continue;
9065                 // generate elements forming a triangle fan for this polygon
9066                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9067         }
9068 }
9069
9070 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)
9071 {
9072         texturelayer_t *layer;
9073         layer = t->currentlayers + t->currentnumlayers++;
9074         layer->type = type;
9075         layer->depthmask = depthmask;
9076         layer->blendfunc1 = blendfunc1;
9077         layer->blendfunc2 = blendfunc2;
9078         layer->texture = texture;
9079         layer->texmatrix = *matrix;
9080         layer->color[0] = r;
9081         layer->color[1] = g;
9082         layer->color[2] = b;
9083         layer->color[3] = a;
9084 }
9085
9086 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9087 {
9088         double index, f;
9089         index = parms[2] + r_refdef.scene.time * parms[3];
9090         index -= floor(index);
9091         switch (func)
9092         {
9093         default:
9094         case Q3WAVEFUNC_NONE:
9095         case Q3WAVEFUNC_NOISE:
9096         case Q3WAVEFUNC_COUNT:
9097                 f = 0;
9098                 break;
9099         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9100         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9101         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9102         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9103         case Q3WAVEFUNC_TRIANGLE:
9104                 index *= 4;
9105                 f = index - floor(index);
9106                 if (index < 1)
9107                         f = f;
9108                 else if (index < 2)
9109                         f = 1 - f;
9110                 else if (index < 3)
9111                         f = -f;
9112                 else
9113                         f = -(1 - f);
9114                 break;
9115         }
9116         return (float)(parms[0] + parms[1] * f);
9117 }
9118
9119 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9120 {
9121         int w, h, idx;
9122         float f;
9123         float tcmat[12];
9124         matrix4x4_t matrix, temp;
9125         switch(tcmod->tcmod)
9126         {
9127                 case Q3TCMOD_COUNT:
9128                 case Q3TCMOD_NONE:
9129                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9130                                 matrix = r_waterscrollmatrix;
9131                         else
9132                                 matrix = identitymatrix;
9133                         break;
9134                 case Q3TCMOD_ENTITYTRANSLATE:
9135                         // this is used in Q3 to allow the gamecode to control texcoord
9136                         // scrolling on the entity, which is not supported in darkplaces yet.
9137                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9138                         break;
9139                 case Q3TCMOD_ROTATE:
9140                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9141                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9142                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9143                         break;
9144                 case Q3TCMOD_SCALE:
9145                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9146                         break;
9147                 case Q3TCMOD_SCROLL:
9148                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9149                         break;
9150                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9151                         w = (int) tcmod->parms[0];
9152                         h = (int) tcmod->parms[1];
9153                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9154                         f = f - floor(f);
9155                         idx = (int) floor(f * w * h);
9156                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9157                         break;
9158                 case Q3TCMOD_STRETCH:
9159                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9160                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9161                         break;
9162                 case Q3TCMOD_TRANSFORM:
9163                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9164                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9165                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9166                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9167                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9168                         break;
9169                 case Q3TCMOD_TURBULENT:
9170                         // this is handled in the RSurf_PrepareVertices function
9171                         matrix = identitymatrix;
9172                         break;
9173         }
9174         temp = *texmatrix;
9175         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9176 }
9177
9178 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9179 {
9180         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9181         char name[MAX_QPATH];
9182         skinframe_t *skinframe;
9183         unsigned char pixels[296*194];
9184         strlcpy(cache->name, skinname, sizeof(cache->name));
9185         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9186         if (developer_loading.integer)
9187                 Con_Printf("loading %s\n", name);
9188         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9189         if (!skinframe || !skinframe->base)
9190         {
9191                 unsigned char *f;
9192                 fs_offset_t filesize;
9193                 skinframe = NULL;
9194                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9195                 if (f)
9196                 {
9197                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9198                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9199                         Mem_Free(f);
9200                 }
9201         }
9202         cache->skinframe = skinframe;
9203 }
9204
9205 texture_t *R_GetCurrentTexture(texture_t *t)
9206 {
9207         int i;
9208         const entity_render_t *ent = rsurface.entity;
9209         dp_model_t *model = ent->model;
9210         q3shaderinfo_layer_tcmod_t *tcmod;
9211
9212         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9213                 return t->currentframe;
9214         t->update_lastrenderframe = r_textureframe;
9215         t->update_lastrenderentity = (void *)ent;
9216
9217         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9218                 t->camera_entity = ent->entitynumber;
9219         else
9220                 t->camera_entity = 0;
9221
9222         // switch to an alternate material if this is a q1bsp animated material
9223         {
9224                 texture_t *texture = t;
9225                 int s = rsurface.ent_skinnum;
9226                 if ((unsigned int)s >= (unsigned int)model->numskins)
9227                         s = 0;
9228                 if (model->skinscenes)
9229                 {
9230                         if (model->skinscenes[s].framecount > 1)
9231                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9232                         else
9233                                 s = model->skinscenes[s].firstframe;
9234                 }
9235                 if (s > 0)
9236                         t = t + s * model->num_surfaces;
9237                 if (t->animated)
9238                 {
9239                         // use an alternate animation if the entity's frame is not 0,
9240                         // and only if the texture has an alternate animation
9241                         if (rsurface.ent_alttextures && t->anim_total[1])
9242                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9243                         else
9244                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9245                 }
9246                 texture->currentframe = t;
9247         }
9248
9249         // update currentskinframe to be a qw skin or animation frame
9250         if (rsurface.ent_qwskin >= 0)
9251         {
9252                 i = rsurface.ent_qwskin;
9253                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9254                 {
9255                         r_qwskincache_size = cl.maxclients;
9256                         if (r_qwskincache)
9257                                 Mem_Free(r_qwskincache);
9258                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9259                 }
9260                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9261                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9262                 t->currentskinframe = r_qwskincache[i].skinframe;
9263                 if (t->currentskinframe == NULL)
9264                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9265         }
9266         else if (t->numskinframes >= 2)
9267                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9268         if (t->backgroundnumskinframes >= 2)
9269                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9270
9271         t->currentmaterialflags = t->basematerialflags;
9272         t->currentalpha = rsurface.colormod[3];
9273         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9274                 t->currentalpha *= r_wateralpha.value;
9275         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9276                 t->currentalpha *= t->r_water_wateralpha;
9277         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9278                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9279         if (!(rsurface.ent_flags & RENDER_LIGHT))
9280                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9281         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9282         {
9283                 // pick a model lighting mode
9284                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9285                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9286                 else
9287                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9288         }
9289         if (rsurface.ent_flags & RENDER_ADDITIVE)
9290                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9291         else if (t->currentalpha < 1)
9292                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9293         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9294                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9295         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9296                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9297         if (t->backgroundnumskinframes)
9298                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9299         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9300         {
9301                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9302                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9303         }
9304         else
9305                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9306         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9307                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9308
9309         // there is no tcmod
9310         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9311         {
9312                 t->currenttexmatrix = r_waterscrollmatrix;
9313                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9314         }
9315         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9316         {
9317                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9318                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9319         }
9320
9321         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9322                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9323         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9324                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9325
9326         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9327         if (t->currentskinframe->qpixels)
9328                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9329         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9330         if (!t->basetexture)
9331                 t->basetexture = r_texture_notexture;
9332         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9333         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9334         t->nmaptexture = t->currentskinframe->nmap;
9335         if (!t->nmaptexture)
9336                 t->nmaptexture = r_texture_blanknormalmap;
9337         t->glosstexture = r_texture_black;
9338         t->glowtexture = t->currentskinframe->glow;
9339         t->fogtexture = t->currentskinframe->fog;
9340         t->reflectmasktexture = t->currentskinframe->reflect;
9341         if (t->backgroundnumskinframes)
9342         {
9343                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9344                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9345                 t->backgroundglosstexture = r_texture_black;
9346                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9347                 if (!t->backgroundnmaptexture)
9348                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9349         }
9350         else
9351         {
9352                 t->backgroundbasetexture = r_texture_white;
9353                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9354                 t->backgroundglosstexture = r_texture_black;
9355                 t->backgroundglowtexture = NULL;
9356         }
9357         t->specularpower = r_shadow_glossexponent.value;
9358         // TODO: store reference values for these in the texture?
9359         t->specularscale = 0;
9360         if (r_shadow_gloss.integer > 0)
9361         {
9362                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9363                 {
9364                         if (r_shadow_glossintensity.value > 0)
9365                         {
9366                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9367                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9368                                 t->specularscale = r_shadow_glossintensity.value;
9369                         }
9370                 }
9371                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9372                 {
9373                         t->glosstexture = r_texture_white;
9374                         t->backgroundglosstexture = r_texture_white;
9375                         t->specularscale = r_shadow_gloss2intensity.value;
9376                         t->specularpower = r_shadow_gloss2exponent.value;
9377                 }
9378         }
9379         t->specularscale *= t->specularscalemod;
9380         t->specularpower *= t->specularpowermod;
9381
9382         // lightmaps mode looks bad with dlights using actual texturing, so turn
9383         // off the colormap and glossmap, but leave the normalmap on as it still
9384         // accurately represents the shading involved
9385         if (gl_lightmaps.integer)
9386         {
9387                 t->basetexture = r_texture_grey128;
9388                 t->pantstexture = r_texture_black;
9389                 t->shirttexture = r_texture_black;
9390                 t->nmaptexture = r_texture_blanknormalmap;
9391                 t->glosstexture = r_texture_black;
9392                 t->glowtexture = NULL;
9393                 t->fogtexture = NULL;
9394                 t->reflectmasktexture = NULL;
9395                 t->backgroundbasetexture = NULL;
9396                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9397                 t->backgroundglosstexture = r_texture_black;
9398                 t->backgroundglowtexture = NULL;
9399                 t->specularscale = 0;
9400                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9401         }
9402
9403         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9404         VectorClear(t->dlightcolor);
9405         t->currentnumlayers = 0;
9406         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9407         {
9408                 int blendfunc1, blendfunc2;
9409                 qboolean depthmask;
9410                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9411                 {
9412                         blendfunc1 = GL_SRC_ALPHA;
9413                         blendfunc2 = GL_ONE;
9414                 }
9415                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9416                 {
9417                         blendfunc1 = GL_SRC_ALPHA;
9418                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9419                 }
9420                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9421                 {
9422                         blendfunc1 = t->customblendfunc[0];
9423                         blendfunc2 = t->customblendfunc[1];
9424                 }
9425                 else
9426                 {
9427                         blendfunc1 = GL_ONE;
9428                         blendfunc2 = GL_ZERO;
9429                 }
9430                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9431                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9432                 {
9433                         // fullbright is not affected by r_refdef.lightmapintensity
9434                         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]);
9435                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9436                                 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]);
9437                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9438                                 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]);
9439                 }
9440                 else
9441                 {
9442                         vec3_t ambientcolor;
9443                         float colorscale;
9444                         // set the color tint used for lights affecting this surface
9445                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9446                         colorscale = 2;
9447                         // q3bsp has no lightmap updates, so the lightstylevalue that
9448                         // would normally be baked into the lightmap must be
9449                         // applied to the color
9450                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9451                         if (model->type == mod_brushq3)
9452                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9453                         colorscale *= r_refdef.lightmapintensity;
9454                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9455                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9456                         // basic lit geometry
9457                         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]);
9458                         // add pants/shirt if needed
9459                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9460                                 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]);
9461                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9462                                 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]);
9463                         // now add ambient passes if needed
9464                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9465                         {
9466                                 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]);
9467                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9468                                         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]);
9469                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9470                                         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]);
9471                         }
9472                 }
9473                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9474                         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]);
9475                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9476                 {
9477                         // if this is opaque use alpha blend which will darken the earlier
9478                         // passes cheaply.
9479                         //
9480                         // if this is an alpha blended material, all the earlier passes
9481                         // were darkened by fog already, so we only need to add the fog
9482                         // color ontop through the fog mask texture
9483                         //
9484                         // if this is an additive blended material, all the earlier passes
9485                         // were darkened by fog already, and we should not add fog color
9486                         // (because the background was not darkened, there is no fog color
9487                         // that was lost behind it).
9488                         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]);
9489                 }
9490         }
9491
9492         return t->currentframe;
9493 }
9494
9495 rsurfacestate_t rsurface;
9496
9497 void R_Mesh_ResizeArrays(int newvertices)
9498 {
9499         unsigned char *base;
9500         size_t size;
9501         if (rsurface.array_size >= newvertices)
9502                 return;
9503         if (rsurface.array_base)
9504                 Mem_Free(rsurface.array_base);
9505         rsurface.array_size = (newvertices + 1023) & ~1023;
9506         size = 0;
9507         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9508         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9509         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9510         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9511         size += rsurface.array_size * sizeof(float[3]);
9512         size += rsurface.array_size * sizeof(float[3]);
9513         size += rsurface.array_size * sizeof(float[3]);
9514         size += rsurface.array_size * sizeof(float[3]);
9515         size += rsurface.array_size * sizeof(float[3]);
9516         size += rsurface.array_size * sizeof(float[3]);
9517         size += rsurface.array_size * sizeof(float[3]);
9518         size += rsurface.array_size * sizeof(float[3]);
9519         size += rsurface.array_size * sizeof(float[4]);
9520         size += rsurface.array_size * sizeof(float[2]);
9521         size += rsurface.array_size * sizeof(float[2]);
9522         size += rsurface.array_size * sizeof(float[4]);
9523         size += rsurface.array_size * sizeof(int[3]);
9524         size += rsurface.array_size * sizeof(unsigned short[3]);
9525         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
9526         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9527         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9528         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9529         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9530         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9531         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9532         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9533         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9534         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9535         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9536         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9537         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9538         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9539         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9540         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9541         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9542         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
9543         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
9544 }
9545
9546 void RSurf_ActiveWorldEntity(void)
9547 {
9548         dp_model_t *model = r_refdef.scene.worldmodel;
9549         //if (rsurface.entity == r_refdef.scene.worldentity)
9550         //      return;
9551         rsurface.entity = r_refdef.scene.worldentity;
9552         rsurface.skeleton = NULL;
9553         rsurface.ent_skinnum = 0;
9554         rsurface.ent_qwskin = -1;
9555         rsurface.ent_shadertime = 0;
9556         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9557         if (rsurface.array_size < model->surfmesh.num_vertices)
9558                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9559         rsurface.matrix = identitymatrix;
9560         rsurface.inversematrix = identitymatrix;
9561         rsurface.matrixscale = 1;
9562         rsurface.inversematrixscale = 1;
9563         R_EntityMatrix(&identitymatrix);
9564         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9565         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9566         rsurface.fograngerecip = r_refdef.fograngerecip;
9567         rsurface.fogheightfade = r_refdef.fogheightfade;
9568         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9569         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9570         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9571         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9572         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9573         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9574         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9575         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9576         rsurface.colormod[3] = 1;
9577         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);
9578         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9579         rsurface.frameblend[0].lerp = 1;
9580         rsurface.ent_alttextures = false;
9581         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9582         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9583         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9584         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9585         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9586         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9587         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9588         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9589         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9590         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9591         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9592         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9593         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9594         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9595         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9596         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9597         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9598         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9599         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9600         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9601         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9602         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9603         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9604         rsurface.modelelement3i = model->surfmesh.data_element3i;
9605         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9606         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9607         rsurface.modelelement3s = model->surfmesh.data_element3s;
9608         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9609         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9610         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9611         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9612         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9613         rsurface.modelsurfaces = model->data_surfaces;
9614         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9615         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9616         rsurface.modelvertexposition = model->surfmesh.vertexposition;
9617         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9618         rsurface.modelgeneratedvertex = false;
9619         rsurface.batchgeneratedvertex = false;
9620         rsurface.batchfirstvertex = 0;
9621         rsurface.batchnumvertices = 0;
9622         rsurface.batchfirsttriangle = 0;
9623         rsurface.batchnumtriangles = 0;
9624         rsurface.batchvertex3f  = NULL;
9625         rsurface.batchvertex3f_vertexbuffer = NULL;
9626         rsurface.batchvertex3f_bufferoffset = 0;
9627         rsurface.batchsvector3f = NULL;
9628         rsurface.batchsvector3f_vertexbuffer = NULL;
9629         rsurface.batchsvector3f_bufferoffset = 0;
9630         rsurface.batchtvector3f = NULL;
9631         rsurface.batchtvector3f_vertexbuffer = NULL;
9632         rsurface.batchtvector3f_bufferoffset = 0;
9633         rsurface.batchnormal3f  = NULL;
9634         rsurface.batchnormal3f_vertexbuffer = NULL;
9635         rsurface.batchnormal3f_bufferoffset = 0;
9636         rsurface.batchlightmapcolor4f = NULL;
9637         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9638         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9639         rsurface.batchtexcoordtexture2f = NULL;
9640         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9641         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9642         rsurface.batchtexcoordlightmap2f = NULL;
9643         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9644         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9645         rsurface.batchvertexmesh = NULL;
9646         rsurface.batchvertexmeshbuffer = NULL;
9647         rsurface.batchvertexposition = NULL;
9648         rsurface.batchvertexpositionbuffer = NULL;
9649         rsurface.batchelement3i = NULL;
9650         rsurface.batchelement3i_indexbuffer = NULL;
9651         rsurface.batchelement3i_bufferoffset = 0;
9652         rsurface.batchelement3s = NULL;
9653         rsurface.batchelement3s_indexbuffer = NULL;
9654         rsurface.batchelement3s_bufferoffset = 0;
9655         rsurface.passcolor4f = NULL;
9656         rsurface.passcolor4f_vertexbuffer = NULL;
9657         rsurface.passcolor4f_bufferoffset = 0;
9658 }
9659
9660 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9661 {
9662         dp_model_t *model = ent->model;
9663         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9664         //      return;
9665         rsurface.entity = (entity_render_t *)ent;
9666         rsurface.skeleton = ent->skeleton;
9667         rsurface.ent_skinnum = ent->skinnum;
9668         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;
9669         rsurface.ent_shadertime = ent->shadertime;
9670         rsurface.ent_flags = ent->flags;
9671         if (rsurface.array_size < model->surfmesh.num_vertices)
9672                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9673         rsurface.matrix = ent->matrix;
9674         rsurface.inversematrix = ent->inversematrix;
9675         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9676         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9677         R_EntityMatrix(&rsurface.matrix);
9678         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9679         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9680         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9681         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9682         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9683         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9684         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9685         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9686         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9687         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9688         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9689         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9690         rsurface.colormod[3] = ent->alpha;
9691         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9692         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9693         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9694         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9695         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9696         if (ent->model->brush.submodel && !prepass)
9697         {
9698                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9699                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9700         }
9701         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9702         {
9703                 if (ent->animcache_vertex3f && !r_framedata_failed)
9704                 {
9705                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9706                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9707                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9708                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9709                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
9710                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
9711                         rsurface.modelvertexposition = ent->animcache_vertexposition;
9712                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
9713                 }
9714                 else if (wanttangents)
9715                 {
9716                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9717                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9718                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9719                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9720                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9721                         rsurface.modelvertexmesh = NULL;
9722                         rsurface.modelvertexmeshbuffer = NULL;
9723                         rsurface.modelvertexposition = NULL;
9724                         rsurface.modelvertexpositionbuffer = NULL;
9725                 }
9726                 else if (wantnormals)
9727                 {
9728                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9729                         rsurface.modelsvector3f = NULL;
9730                         rsurface.modeltvector3f = NULL;
9731                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9732                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9733                         rsurface.modelvertexmesh = NULL;
9734                         rsurface.modelvertexmeshbuffer = NULL;
9735                         rsurface.modelvertexposition = NULL;
9736                         rsurface.modelvertexpositionbuffer = NULL;
9737                 }
9738                 else
9739                 {
9740                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9741                         rsurface.modelsvector3f = NULL;
9742                         rsurface.modeltvector3f = NULL;
9743                         rsurface.modelnormal3f = NULL;
9744                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9745                         rsurface.modelvertexmesh = NULL;
9746                         rsurface.modelvertexmeshbuffer = NULL;
9747                         rsurface.modelvertexposition = NULL;
9748                         rsurface.modelvertexpositionbuffer = NULL;
9749                 }
9750                 rsurface.modelvertex3f_vertexbuffer = 0;
9751                 rsurface.modelvertex3f_bufferoffset = 0;
9752                 rsurface.modelsvector3f_vertexbuffer = 0;
9753                 rsurface.modelsvector3f_bufferoffset = 0;
9754                 rsurface.modeltvector3f_vertexbuffer = 0;
9755                 rsurface.modeltvector3f_bufferoffset = 0;
9756                 rsurface.modelnormal3f_vertexbuffer = 0;
9757                 rsurface.modelnormal3f_bufferoffset = 0;
9758                 rsurface.modelgeneratedvertex = true;
9759         }
9760         else
9761         {
9762                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9763                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9764                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9765                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9766                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9767                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9768                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9769                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9770                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9771                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9772                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9773                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9774                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9775                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9776                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
9777                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9778                 rsurface.modelgeneratedvertex = false;
9779         }
9780         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9781         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9782         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9783         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9784         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9785         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9786         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9787         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9788         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9789         rsurface.modelelement3i = model->surfmesh.data_element3i;
9790         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9791         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9792         rsurface.modelelement3s = model->surfmesh.data_element3s;
9793         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9794         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9795         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9796         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9797         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9798         rsurface.modelsurfaces = model->data_surfaces;
9799         rsurface.batchgeneratedvertex = false;
9800         rsurface.batchfirstvertex = 0;
9801         rsurface.batchnumvertices = 0;
9802         rsurface.batchfirsttriangle = 0;
9803         rsurface.batchnumtriangles = 0;
9804         rsurface.batchvertex3f  = NULL;
9805         rsurface.batchvertex3f_vertexbuffer = NULL;
9806         rsurface.batchvertex3f_bufferoffset = 0;
9807         rsurface.batchsvector3f = NULL;
9808         rsurface.batchsvector3f_vertexbuffer = NULL;
9809         rsurface.batchsvector3f_bufferoffset = 0;
9810         rsurface.batchtvector3f = NULL;
9811         rsurface.batchtvector3f_vertexbuffer = NULL;
9812         rsurface.batchtvector3f_bufferoffset = 0;
9813         rsurface.batchnormal3f  = NULL;
9814         rsurface.batchnormal3f_vertexbuffer = NULL;
9815         rsurface.batchnormal3f_bufferoffset = 0;
9816         rsurface.batchlightmapcolor4f = NULL;
9817         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9818         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9819         rsurface.batchtexcoordtexture2f = NULL;
9820         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9821         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9822         rsurface.batchtexcoordlightmap2f = NULL;
9823         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9824         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9825         rsurface.batchvertexmesh = NULL;
9826         rsurface.batchvertexmeshbuffer = NULL;
9827         rsurface.batchvertexposition = NULL;
9828         rsurface.batchvertexpositionbuffer = NULL;
9829         rsurface.batchelement3i = NULL;
9830         rsurface.batchelement3i_indexbuffer = NULL;
9831         rsurface.batchelement3i_bufferoffset = 0;
9832         rsurface.batchelement3s = NULL;
9833         rsurface.batchelement3s_indexbuffer = NULL;
9834         rsurface.batchelement3s_bufferoffset = 0;
9835         rsurface.passcolor4f = NULL;
9836         rsurface.passcolor4f_vertexbuffer = NULL;
9837         rsurface.passcolor4f_bufferoffset = 0;
9838 }
9839
9840 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)
9841 {
9842         int i;
9843
9844         rsurface.entity = r_refdef.scene.worldentity;
9845         rsurface.skeleton = NULL;
9846         rsurface.ent_skinnum = 0;
9847         rsurface.ent_qwskin = -1;
9848         rsurface.ent_shadertime = shadertime;
9849         rsurface.ent_flags = entflags;
9850         rsurface.modelnumvertices = numvertices;
9851         rsurface.modelnumtriangles = numtriangles;
9852         if (rsurface.array_size < rsurface.modelnumvertices)
9853                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
9854         rsurface.matrix = *matrix;
9855         rsurface.inversematrix = *inversematrix;
9856         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9857         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9858         R_EntityMatrix(&rsurface.matrix);
9859         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9860         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9861         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9862         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9863         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9864         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9865         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9866         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9867         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9868         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9869         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9870         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9871         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);
9872         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9873         rsurface.frameblend[0].lerp = 1;
9874         rsurface.ent_alttextures = false;
9875         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9876         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9877         if (wanttangents)
9878         {
9879                 rsurface.modelvertex3f = vertex3f;
9880                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9881                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9882                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9883         }
9884         else if (wantnormals)
9885         {
9886                 rsurface.modelvertex3f = vertex3f;
9887                 rsurface.modelsvector3f = NULL;
9888                 rsurface.modeltvector3f = NULL;
9889                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9890         }
9891         else
9892         {
9893                 rsurface.modelvertex3f = vertex3f;
9894                 rsurface.modelsvector3f = NULL;
9895                 rsurface.modeltvector3f = NULL;
9896                 rsurface.modelnormal3f = NULL;
9897         }
9898         rsurface.modelvertexmesh = NULL;
9899         rsurface.modelvertexmeshbuffer = NULL;
9900         rsurface.modelvertexposition = NULL;
9901         rsurface.modelvertexpositionbuffer = NULL;
9902         rsurface.modelvertex3f_vertexbuffer = 0;
9903         rsurface.modelvertex3f_bufferoffset = 0;
9904         rsurface.modelsvector3f_vertexbuffer = 0;
9905         rsurface.modelsvector3f_bufferoffset = 0;
9906         rsurface.modeltvector3f_vertexbuffer = 0;
9907         rsurface.modeltvector3f_bufferoffset = 0;
9908         rsurface.modelnormal3f_vertexbuffer = 0;
9909         rsurface.modelnormal3f_bufferoffset = 0;
9910         rsurface.modelgeneratedvertex = true;
9911         rsurface.modellightmapcolor4f  = color4f;
9912         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9913         rsurface.modellightmapcolor4f_bufferoffset = 0;
9914         rsurface.modeltexcoordtexture2f  = texcoord2f;
9915         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9916         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9917         rsurface.modeltexcoordlightmap2f  = NULL;
9918         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9919         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9920         rsurface.modelelement3i = element3i;
9921         rsurface.modelelement3i_indexbuffer = NULL;
9922         rsurface.modelelement3i_bufferoffset = 0;
9923         rsurface.modelelement3s = element3s;
9924         rsurface.modelelement3s_indexbuffer = NULL;
9925         rsurface.modelelement3s_bufferoffset = 0;
9926         rsurface.modellightmapoffsets = NULL;
9927         rsurface.modelsurfaces = NULL;
9928         rsurface.batchgeneratedvertex = false;
9929         rsurface.batchfirstvertex = 0;
9930         rsurface.batchnumvertices = 0;
9931         rsurface.batchfirsttriangle = 0;
9932         rsurface.batchnumtriangles = 0;
9933         rsurface.batchvertex3f  = NULL;
9934         rsurface.batchvertex3f_vertexbuffer = NULL;
9935         rsurface.batchvertex3f_bufferoffset = 0;
9936         rsurface.batchsvector3f = NULL;
9937         rsurface.batchsvector3f_vertexbuffer = NULL;
9938         rsurface.batchsvector3f_bufferoffset = 0;
9939         rsurface.batchtvector3f = NULL;
9940         rsurface.batchtvector3f_vertexbuffer = NULL;
9941         rsurface.batchtvector3f_bufferoffset = 0;
9942         rsurface.batchnormal3f  = NULL;
9943         rsurface.batchnormal3f_vertexbuffer = NULL;
9944         rsurface.batchnormal3f_bufferoffset = 0;
9945         rsurface.batchlightmapcolor4f = NULL;
9946         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9947         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9948         rsurface.batchtexcoordtexture2f = NULL;
9949         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9950         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9951         rsurface.batchtexcoordlightmap2f = NULL;
9952         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9953         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9954         rsurface.batchvertexmesh = NULL;
9955         rsurface.batchvertexmeshbuffer = NULL;
9956         rsurface.batchvertexposition = NULL;
9957         rsurface.batchvertexpositionbuffer = NULL;
9958         rsurface.batchelement3i = NULL;
9959         rsurface.batchelement3i_indexbuffer = NULL;
9960         rsurface.batchelement3i_bufferoffset = 0;
9961         rsurface.batchelement3s = NULL;
9962         rsurface.batchelement3s_indexbuffer = NULL;
9963         rsurface.batchelement3s_bufferoffset = 0;
9964         rsurface.passcolor4f = NULL;
9965         rsurface.passcolor4f_vertexbuffer = NULL;
9966         rsurface.passcolor4f_bufferoffset = 0;
9967
9968         if (rsurface.modelnumvertices && rsurface.modelelement3i)
9969         {
9970                 if ((wantnormals || wanttangents) && !normal3f)
9971                 {
9972                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9973                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9974                 }
9975                 if (wanttangents && !svector3f)
9976                 {
9977                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9978                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9979                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9980                 }
9981         }
9982
9983         // now convert arrays into vertexmesh structs
9984         for (i = 0;i < numvertices;i++)
9985         {
9986                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
9987                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
9988                 if (rsurface.modelsvector3f)
9989                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
9990                 if (rsurface.modeltvector3f)
9991                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
9992                 if (rsurface.modelnormal3f)
9993                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
9994                 if (rsurface.modellightmapcolor4f)
9995                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
9996                 if (rsurface.modeltexcoordtexture2f)
9997                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
9998                 if (rsurface.modeltexcoordlightmap2f)
9999                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10000         }
10001 }
10002
10003 float RSurf_FogPoint(const float *v)
10004 {
10005         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10006         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10007         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10008         float FogHeightFade = r_refdef.fogheightfade;
10009         float fogfrac;
10010         unsigned int fogmasktableindex;
10011         if (r_refdef.fogplaneviewabove)
10012                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10013         else
10014                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10015         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10016         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10017 }
10018
10019 float RSurf_FogVertex(const float *v)
10020 {
10021         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10022         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10023         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10024         float FogHeightFade = rsurface.fogheightfade;
10025         float fogfrac;
10026         unsigned int fogmasktableindex;
10027         if (r_refdef.fogplaneviewabove)
10028                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10029         else
10030                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10031         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10032         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10033 }
10034
10035 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10036 {
10037         int i;
10038         for (i = 0;i < numelements;i++)
10039                 outelement3i[i] = inelement3i[i] + adjust;
10040 }
10041
10042 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10043 extern cvar_t gl_vbo;
10044 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10045 {
10046         int deformindex;
10047         int firsttriangle;
10048         int numtriangles;
10049         int firstvertex;
10050         int endvertex;
10051         int numvertices;
10052         int surfacefirsttriangle;
10053         int surfacenumtriangles;
10054         int surfacefirstvertex;
10055         int surfaceendvertex;
10056         int surfacenumvertices;
10057         int surfaceadjustvertex;
10058         int needsupdate;
10059         int i, j;
10060         qboolean gaps;
10061         qboolean dynamicvertex;
10062         float amplitude;
10063         float animpos;
10064         float scale;
10065         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10066         float waveparms[4];
10067         q3shaderinfo_deform_t *deform;
10068         const msurface_t *surface, *firstsurface;
10069         r_vertexposition_t *vertexposition;
10070         r_vertexmesh_t *vertexmesh;
10071         if (!texturenumsurfaces)
10072                 return;
10073         // find vertex range of this surface batch
10074         gaps = false;
10075         firstsurface = texturesurfacelist[0];
10076         firsttriangle = firstsurface->num_firsttriangle;
10077         numtriangles = 0;
10078         firstvertex = endvertex = firstsurface->num_firstvertex;
10079         for (i = 0;i < texturenumsurfaces;i++)
10080         {
10081                 surface = texturesurfacelist[i];
10082                 if (surface != firstsurface + i)
10083                         gaps = true;
10084                 surfacefirstvertex = surface->num_firstvertex;
10085                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10086                 surfacenumtriangles = surface->num_triangles;
10087                 if (firstvertex > surfacefirstvertex)
10088                         firstvertex = surfacefirstvertex;
10089                 if (endvertex < surfaceendvertex)
10090                         endvertex = surfaceendvertex;
10091                 numtriangles += surfacenumtriangles;
10092         }
10093         if (!numtriangles)
10094                 return;
10095
10096         // we now know the vertex range used, and if there are any gaps in it
10097         rsurface.batchfirstvertex = firstvertex;
10098         rsurface.batchnumvertices = endvertex - firstvertex;
10099         rsurface.batchfirsttriangle = firsttriangle;
10100         rsurface.batchnumtriangles = numtriangles;
10101
10102         // this variable holds flags for which properties have been updated that
10103         // may require regenerating vertexmesh or vertexposition arrays...
10104         needsupdate = 0;
10105
10106         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10107                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
10108         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10109         {
10110                 switch (deform->deform)
10111                 {
10112                 default:
10113                 case Q3DEFORM_PROJECTIONSHADOW:
10114                 case Q3DEFORM_TEXT0:
10115                 case Q3DEFORM_TEXT1:
10116                 case Q3DEFORM_TEXT2:
10117                 case Q3DEFORM_TEXT3:
10118                 case Q3DEFORM_TEXT4:
10119                 case Q3DEFORM_TEXT5:
10120                 case Q3DEFORM_TEXT6:
10121                 case Q3DEFORM_TEXT7:
10122                 case Q3DEFORM_NONE:
10123                         break;
10124                 case Q3DEFORM_AUTOSPRITE:
10125                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10126                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10127                         break;
10128                 case Q3DEFORM_AUTOSPRITE2:
10129                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10130                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10131                         break;
10132                 case Q3DEFORM_NORMAL:
10133                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10134                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10135                         break;
10136                 case Q3DEFORM_WAVE:
10137                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10138                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10139                         break;
10140                 case Q3DEFORM_BULGE:
10141                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10142                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10143                         break;
10144                 case Q3DEFORM_MOVE:
10145                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10146                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
10147                         break;
10148                 }
10149         }
10150         switch(rsurface.texture->tcgen.tcgen)
10151         {
10152         default:
10153         case Q3TCGEN_TEXTURE:
10154                 break;
10155         case Q3TCGEN_LIGHTMAP:
10156                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10157                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10158                 break;
10159         case Q3TCGEN_VECTOR:
10160                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10161                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10162                 break;
10163         case Q3TCGEN_ENVIRONMENT:
10164                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10165                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10166                 break;
10167         }
10168         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10169         {
10170                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10171                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10172         }
10173
10174         // check if any dynamic vertex processing must occur
10175         dynamicvertex = false;
10176
10177         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10178         {
10179                 dynamicvertex = true;
10180                 batchneed |= BATCHNEED_NOGAPS;
10181                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10182         }
10183
10184         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10185         {
10186                 dynamicvertex = true;
10187                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10188                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
10189         }
10190
10191         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10192         {
10193                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10194                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10195                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10196                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10197                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10198                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10199                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10200         }
10201
10202         // when the model data has no vertex buffer (dynamic mesh), we need to
10203         // eliminate gaps
10204         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
10205                 batchneed |= BATCHNEED_NOGAPS;
10206
10207         // if needsupdate, we have to do a dynamic vertex batch for sure
10208         if (needsupdate & batchneed)
10209                 dynamicvertex = true;
10210
10211         // see if we need to build vertexmesh from arrays
10212         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10213                 dynamicvertex = true;
10214
10215         // see if we need to build vertexposition from arrays
10216         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
10217                 dynamicvertex = true;
10218
10219         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10220         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10221                 dynamicvertex = true;
10222
10223         // if there is a chance of animated vertex colors, it's a dynamic batch
10224         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10225                 dynamicvertex = true;
10226
10227         rsurface.batchvertex3f = rsurface.modelvertex3f;
10228         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10229         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10230         rsurface.batchsvector3f = rsurface.modelsvector3f;
10231         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10232         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10233         rsurface.batchtvector3f = rsurface.modeltvector3f;
10234         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10235         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10236         rsurface.batchnormal3f = rsurface.modelnormal3f;
10237         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10238         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10239         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10240         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10241         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10242         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10243         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10244         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10245         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10246         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10247         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10248         rsurface.batchvertexposition = rsurface.modelvertexposition;
10249         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
10250         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10251         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10252         rsurface.batchelement3i = rsurface.modelelement3i;
10253         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10254         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10255         rsurface.batchelement3s = rsurface.modelelement3s;
10256         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10257         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10258
10259         // if any dynamic vertex processing has to occur in software, we copy the
10260         // entire surface list together before processing to rebase the vertices
10261         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10262         //
10263         // if any gaps exist and we do not have a static vertex buffer, we have to
10264         // copy the surface list together to avoid wasting upload bandwidth on the
10265         // vertices in the gaps.
10266         //
10267         // if gaps exist and we have a static vertex buffer, we still have to
10268         // combine the index buffer ranges into one dynamic index buffer.
10269         //
10270         // in all cases we end up with data that can be drawn in one call.
10271
10272         if (!dynamicvertex)
10273         {
10274                 // static vertex data, just set pointers...
10275                 rsurface.batchgeneratedvertex = false;
10276                 // if there are gaps, we want to build a combined index buffer,
10277                 // otherwise use the original static buffer with an appropriate offset
10278                 if (gaps)
10279                 {
10280                         firsttriangle = 0;
10281                         numtriangles = 0;
10282                         for (i = 0;i < texturenumsurfaces;i++)
10283                         {
10284                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10285                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10286                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
10287                                 numtriangles += surfacenumtriangles;
10288                         }
10289                         rsurface.batchelement3i = rsurface.array_batchelement3i;
10290                         rsurface.batchelement3i_indexbuffer = NULL;
10291                         rsurface.batchelement3i_bufferoffset = 0;
10292                         rsurface.batchelement3s = NULL;
10293                         rsurface.batchelement3s_indexbuffer = NULL;
10294                         rsurface.batchelement3s_bufferoffset = 0;
10295                         if (endvertex <= 65536)
10296                         {
10297                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
10298                                 for (i = 0;i < numtriangles*3;i++)
10299                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10300                         }
10301                         rsurface.batchfirsttriangle = firsttriangle;
10302                         rsurface.batchnumtriangles = numtriangles;
10303                 }
10304                 return;
10305         }
10306
10307         // something needs software processing, do it for real...
10308         // we only directly handle interleaved array data in this case...
10309         rsurface.batchgeneratedvertex = true;
10310
10311         // now copy the vertex data into a combined array and make an index array
10312         // (this is what Quake3 does all the time)
10313         //if (gaps || rsurface.batchfirstvertex)
10314         {
10315                 rsurface.batchvertexposition = NULL;
10316                 rsurface.batchvertexpositionbuffer = NULL;
10317                 rsurface.batchvertexmesh = NULL;
10318                 rsurface.batchvertexmeshbuffer = NULL;
10319                 rsurface.batchvertex3f = NULL;
10320                 rsurface.batchvertex3f_vertexbuffer = NULL;
10321                 rsurface.batchvertex3f_bufferoffset = 0;
10322                 rsurface.batchsvector3f = NULL;
10323                 rsurface.batchsvector3f_vertexbuffer = NULL;
10324                 rsurface.batchsvector3f_bufferoffset = 0;
10325                 rsurface.batchtvector3f = NULL;
10326                 rsurface.batchtvector3f_vertexbuffer = NULL;
10327                 rsurface.batchtvector3f_bufferoffset = 0;
10328                 rsurface.batchnormal3f = NULL;
10329                 rsurface.batchnormal3f_vertexbuffer = NULL;
10330                 rsurface.batchnormal3f_bufferoffset = 0;
10331                 rsurface.batchlightmapcolor4f = NULL;
10332                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10333                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10334                 rsurface.batchtexcoordtexture2f = NULL;
10335                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10336                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10337                 rsurface.batchtexcoordlightmap2f = NULL;
10338                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10339                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10340                 rsurface.batchelement3i = rsurface.array_batchelement3i;
10341                 rsurface.batchelement3i_indexbuffer = NULL;
10342                 rsurface.batchelement3i_bufferoffset = 0;
10343                 rsurface.batchelement3s = NULL;
10344                 rsurface.batchelement3s_indexbuffer = NULL;
10345                 rsurface.batchelement3s_bufferoffset = 0;
10346                 // we'll only be setting up certain arrays as needed
10347                 if (batchneed & BATCHNEED_VERTEXPOSITION)
10348                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10349                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10350                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10351                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10352                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10353                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
10354                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10355                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
10356                 {
10357                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10358                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10359                 }
10360                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
10361                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10362                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
10363                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10364                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
10365                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
10366                 numvertices = 0;
10367                 numtriangles = 0;
10368                 for (i = 0;i < texturenumsurfaces;i++)
10369                 {
10370                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
10371                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
10372                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10373                         surfaceadjustvertex = numvertices - surfacefirstvertex;
10374                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10375                         // copy only the data requested
10376                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
10377                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
10378                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
10379                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
10380                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
10381                         {
10382                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10383                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10384                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
10385                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10386                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
10387                                 {
10388                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10389                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10390                                 }
10391                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
10392                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
10393                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
10394                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10395                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
10396                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10397                         }
10398                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
10399                         numvertices += surfacenumvertices;
10400                         numtriangles += surfacenumtriangles;
10401                 }
10402
10403                 // generate a 16bit index array as well if possible
10404                 // (in general, dynamic batches fit)
10405                 if (numvertices <= 65536)
10406                 {
10407                         rsurface.batchelement3s = rsurface.array_batchelement3s;
10408                         for (i = 0;i < numtriangles*3;i++)
10409                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10410                 }
10411
10412                 // since we've copied everything, the batch now starts at 0
10413                 rsurface.batchfirstvertex = 0;
10414                 rsurface.batchnumvertices = numvertices;
10415                 rsurface.batchfirsttriangle = 0;
10416                 rsurface.batchnumtriangles = numtriangles;
10417         }
10418
10419         // q1bsp surfaces rendered in vertex color mode have to have colors
10420         // calculated based on lightstyles
10421         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10422         {
10423                 // generate color arrays for the surfaces in this list
10424                 int c[4];
10425                 int scale;
10426                 int size3;
10427                 const int *offsets;
10428                 const unsigned char *lm;
10429                 numvertices = 0;
10430                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10431                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10432                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10433                 for (i = 0;i < texturenumsurfaces;i++)
10434                 {
10435                         surface = texturesurfacelist[i];
10436                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10437                         surfacenumvertices = surface->num_vertices;
10438                         if (surface->lightmapinfo->samples)
10439                         {
10440                                 for (j = 0;j < surfacenumvertices;j++)
10441                                 {
10442                                         lm = surface->lightmapinfo->samples + offsets[j];
10443                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10444                                         VectorScale(lm, scale, c);
10445                                         if (surface->lightmapinfo->styles[1] != 255)
10446                                         {
10447                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10448                                                 lm += size3;
10449                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10450                                                 VectorMA(c, scale, lm, c);
10451                                                 if (surface->lightmapinfo->styles[2] != 255)
10452                                                 {
10453                                                         lm += size3;
10454                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10455                                                         VectorMA(c, scale, lm, c);
10456                                                         if (surface->lightmapinfo->styles[3] != 255)
10457                                                         {
10458                                                                 lm += size3;
10459                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10460                                                                 VectorMA(c, scale, lm, c);
10461                                                         }
10462                                                 }
10463                                         }
10464                                         c[0] >>= 15;
10465                                         c[1] >>= 15;
10466                                         c[2] >>= 15;
10467                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, min(c[0], 255) * (1.0f / 255.0f), min(c[1], 255) * (1.0f / 255.0f), min(c[2], 255) * (1.0f / 255.0f), 1);
10468                                         numvertices++;
10469                                 }
10470                         }
10471                         else
10472                         {
10473                                 for (j = 0;j < surfacenumvertices;j++)
10474                                 {
10475                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10476                                         numvertices++;
10477                                 }
10478                         }
10479                 }
10480         }
10481
10482         // if vertices are deformed (sprite flares and things in maps, possibly
10483         // water waves, bulges and other deformations), modify the copied vertices
10484         // in place
10485         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10486         {
10487                 switch (deform->deform)
10488                 {
10489                 default:
10490                 case Q3DEFORM_PROJECTIONSHADOW:
10491                 case Q3DEFORM_TEXT0:
10492                 case Q3DEFORM_TEXT1:
10493                 case Q3DEFORM_TEXT2:
10494                 case Q3DEFORM_TEXT3:
10495                 case Q3DEFORM_TEXT4:
10496                 case Q3DEFORM_TEXT5:
10497                 case Q3DEFORM_TEXT6:
10498                 case Q3DEFORM_TEXT7:
10499                 case Q3DEFORM_NONE:
10500                         break;
10501                 case Q3DEFORM_AUTOSPRITE:
10502                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10503                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10504                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10505                         VectorNormalize(newforward);
10506                         VectorNormalize(newright);
10507                         VectorNormalize(newup);
10508                         // a single autosprite surface can contain multiple sprites...
10509                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10510                         {
10511                                 VectorClear(center);
10512                                 for (i = 0;i < 4;i++)
10513                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10514                                 VectorScale(center, 0.25f, center);
10515                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10516                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10517                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10518                                 for (i = 0;i < 4;i++)
10519                                 {
10520                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10521                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
10522                                 }
10523                         }
10524                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10525                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10526                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10527                         rsurface.batchvertex3f_vertexbuffer = NULL;
10528                         rsurface.batchvertex3f_bufferoffset = 0;
10529                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10530                         rsurface.batchsvector3f_vertexbuffer = NULL;
10531                         rsurface.batchsvector3f_bufferoffset = 0;
10532                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10533                         rsurface.batchtvector3f_vertexbuffer = NULL;
10534                         rsurface.batchtvector3f_bufferoffset = 0;
10535                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10536                         rsurface.batchnormal3f_vertexbuffer = NULL;
10537                         rsurface.batchnormal3f_bufferoffset = 0;
10538                         break;
10539                 case Q3DEFORM_AUTOSPRITE2:
10540                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10541                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10542                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10543                         VectorNormalize(newforward);
10544                         VectorNormalize(newright);
10545                         VectorNormalize(newup);
10546                         {
10547                                 const float *v1, *v2;
10548                                 vec3_t start, end;
10549                                 float f, l;
10550                                 struct
10551                                 {
10552                                         float length2;
10553                                         const float *v1;
10554                                         const float *v2;
10555                                 }
10556                                 shortest[2];
10557                                 memset(shortest, 0, sizeof(shortest));
10558                                 // a single autosprite surface can contain multiple sprites...
10559                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10560                                 {
10561                                         VectorClear(center);
10562                                         for (i = 0;i < 4;i++)
10563                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10564                                         VectorScale(center, 0.25f, center);
10565                                         // find the two shortest edges, then use them to define the
10566                                         // axis vectors for rotating around the central axis
10567                                         for (i = 0;i < 6;i++)
10568                                         {
10569                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10570                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10571                                                 l = VectorDistance2(v1, v2);
10572                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10573                                                 if (v1[2] != v2[2])
10574                                                         l += (1.0f / 1024.0f);
10575                                                 if (shortest[0].length2 > l || i == 0)
10576                                                 {
10577                                                         shortest[1] = shortest[0];
10578                                                         shortest[0].length2 = l;
10579                                                         shortest[0].v1 = v1;
10580                                                         shortest[0].v2 = v2;
10581                                                 }
10582                                                 else if (shortest[1].length2 > l || i == 1)
10583                                                 {
10584                                                         shortest[1].length2 = l;
10585                                                         shortest[1].v1 = v1;
10586                                                         shortest[1].v2 = v2;
10587                                                 }
10588                                         }
10589                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10590                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10591                                         // this calculates the right vector from the shortest edge
10592                                         // and the up vector from the edge midpoints
10593                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10594                                         VectorNormalize(right);
10595                                         VectorSubtract(end, start, up);
10596                                         VectorNormalize(up);
10597                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10598                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10599                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10600                                         VectorNegate(forward, forward);
10601                                         VectorReflect(forward, 0, up, forward);
10602                                         VectorNormalize(forward);
10603                                         CrossProduct(up, forward, newright);
10604                                         VectorNormalize(newright);
10605                                         // rotate the quad around the up axis vector, this is made
10606                                         // especially easy by the fact we know the quad is flat,
10607                                         // so we only have to subtract the center position and
10608                                         // measure distance along the right vector, and then
10609                                         // multiply that by the newright vector and add back the
10610                                         // center position
10611                                         // we also need to subtract the old position to undo the
10612                                         // displacement from the center, which we do with a
10613                                         // DotProduct, the subtraction/addition of center is also
10614                                         // optimized into DotProducts here
10615                                         l = DotProduct(right, center);
10616                                         for (i = 0;i < 4;i++)
10617                                         {
10618                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10619                                                 f = DotProduct(right, v1) - l;
10620                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
10621                                         }
10622                                 }
10623                         }
10624                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10625                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10626                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10627                         rsurface.batchvertex3f_vertexbuffer = NULL;
10628                         rsurface.batchvertex3f_bufferoffset = 0;
10629                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10630                         rsurface.batchsvector3f_vertexbuffer = NULL;
10631                         rsurface.batchsvector3f_bufferoffset = 0;
10632                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10633                         rsurface.batchtvector3f_vertexbuffer = NULL;
10634                         rsurface.batchtvector3f_bufferoffset = 0;
10635                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10636                         rsurface.batchnormal3f_vertexbuffer = NULL;
10637                         rsurface.batchnormal3f_bufferoffset = 0;
10638                         break;
10639                 case Q3DEFORM_NORMAL:
10640                         // deform the normals to make reflections wavey
10641                         for (j = 0;j < rsurface.batchnumvertices;j++)
10642                         {
10643                                 float vertex[3];
10644                                 float *normal = rsurface.array_batchnormal3f + 3*j;
10645                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10646                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10647                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10648                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10649                                 VectorNormalize(normal);
10650                         }
10651                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10652                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10653                         rsurface.batchsvector3f_vertexbuffer = NULL;
10654                         rsurface.batchsvector3f_bufferoffset = 0;
10655                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10656                         rsurface.batchtvector3f_vertexbuffer = NULL;
10657                         rsurface.batchtvector3f_bufferoffset = 0;
10658                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10659                         rsurface.batchnormal3f_vertexbuffer = NULL;
10660                         rsurface.batchnormal3f_bufferoffset = 0;
10661                         break;
10662                 case Q3DEFORM_WAVE:
10663                         // deform vertex array to make wavey water and flags and such
10664                         waveparms[0] = deform->waveparms[0];
10665                         waveparms[1] = deform->waveparms[1];
10666                         waveparms[2] = deform->waveparms[2];
10667                         waveparms[3] = deform->waveparms[3];
10668                         // this is how a divisor of vertex influence on deformation
10669                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10670                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10671                         for (j = 0;j < rsurface.batchnumvertices;j++)
10672                         {
10673                                 // if the wavefunc depends on time, evaluate it per-vertex
10674                                 if (waveparms[3])
10675                                 {
10676                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10677                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10678                                 }
10679                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10680                         }
10681                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10682                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10683                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10684                         rsurface.batchvertex3f_vertexbuffer = NULL;
10685                         rsurface.batchvertex3f_bufferoffset = 0;
10686                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10687                         rsurface.batchsvector3f_vertexbuffer = NULL;
10688                         rsurface.batchsvector3f_bufferoffset = 0;
10689                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10690                         rsurface.batchtvector3f_vertexbuffer = NULL;
10691                         rsurface.batchtvector3f_bufferoffset = 0;
10692                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10693                         rsurface.batchnormal3f_vertexbuffer = NULL;
10694                         rsurface.batchnormal3f_bufferoffset = 0;
10695                         break;
10696                 case Q3DEFORM_BULGE:
10697                         // deform vertex array to make the surface have moving bulges
10698                         for (j = 0;j < rsurface.batchnumvertices;j++)
10699                         {
10700                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
10701                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10702                         }
10703                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10704                         Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.array_batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchsvector3f, rsurface.array_batchtvector3f, true);
10705                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10706                         rsurface.batchvertex3f_vertexbuffer = NULL;
10707                         rsurface.batchvertex3f_bufferoffset = 0;
10708                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10709                         rsurface.batchsvector3f_vertexbuffer = NULL;
10710                         rsurface.batchsvector3f_bufferoffset = 0;
10711                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10712                         rsurface.batchtvector3f_vertexbuffer = NULL;
10713                         rsurface.batchtvector3f_bufferoffset = 0;
10714                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10715                         rsurface.batchnormal3f_vertexbuffer = NULL;
10716                         rsurface.batchnormal3f_bufferoffset = 0;
10717                         break;
10718                 case Q3DEFORM_MOVE:
10719                         // deform vertex array
10720                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10721                         VectorScale(deform->parms, scale, waveparms);
10722                         for (j = 0;j < rsurface.batchnumvertices;j++)
10723                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
10724                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10725                         rsurface.batchvertex3f_vertexbuffer = NULL;
10726                         rsurface.batchvertex3f_bufferoffset = 0;
10727                         break;
10728                 }
10729         }
10730
10731         // generate texcoords based on the chosen texcoord source
10732         switch(rsurface.texture->tcgen.tcgen)
10733         {
10734         default:
10735         case Q3TCGEN_TEXTURE:
10736                 break;
10737         case Q3TCGEN_LIGHTMAP:
10738                 if (rsurface.batchtexcoordlightmap2f)
10739                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
10740                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10741                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10742                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10743                 break;
10744         case Q3TCGEN_VECTOR:
10745                 for (j = 0;j < rsurface.batchnumvertices;j++)
10746                 {
10747                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10748                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10749                 }
10750                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10751                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10752                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10753                 break;
10754         case Q3TCGEN_ENVIRONMENT:
10755                 // make environment reflections using a spheremap
10756                 for (j = 0;j < rsurface.batchnumvertices;j++)
10757                 {
10758                         // identical to Q3A's method, but executed in worldspace so
10759                         // carried models can be shiny too
10760
10761                         float viewer[3], d, reflected[3], worldreflected[3];
10762
10763                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10764                         // VectorNormalize(viewer);
10765
10766                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10767
10768                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10769                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10770                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10771                         // note: this is proportinal to viewer, so we can normalize later
10772
10773                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10774                         VectorNormalize(worldreflected);
10775
10776                         // note: this sphere map only uses world x and z!
10777                         // so positive and negative y will LOOK THE SAME.
10778                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10779                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10780                 }
10781                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10782                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10783                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10784                 break;
10785         }
10786         // the only tcmod that needs software vertex processing is turbulent, so
10787         // check for it here and apply the changes if needed
10788         // and we only support that as the first one
10789         // (handling a mixture of turbulent and other tcmods would be problematic
10790         //  without punting it entirely to a software path)
10791         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10792         {
10793                 amplitude = rsurface.texture->tcmods[0].parms[1];
10794                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10795                 for (j = 0;j < rsurface.batchnumvertices;j++)
10796                 {
10797                         rsurface.array_batchtexcoordtexture2f[j*2+0] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10798                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10799                 }
10800                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10801                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10802                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10803         }
10804
10805         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10806         {
10807                 // convert the modified arrays to vertex structs
10808                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10809                 rsurface.batchvertexmeshbuffer = NULL;
10810                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10811                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10812                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10813                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10814                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10815                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10816                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10817                 {
10818                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10819                         {
10820                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10821                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10822                         }
10823                 }
10824                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10825                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10826                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
10827                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10828                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10829                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10830                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10831                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10832                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10833         }
10834
10835         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10836         {
10837                 // convert the modified arrays to vertex structs
10838                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10839                 rsurface.batchvertexpositionbuffer = NULL;
10840                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
10841                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
10842                 else
10843                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
10844                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
10845         }
10846 }
10847
10848 void RSurf_DrawBatch(void)
10849 {
10850         R_Mesh_Draw(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchfirsttriangle, rsurface.batchnumtriangles, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
10851 }
10852
10853 static void RSurf_BindLightmapForBatch(void)
10854 {
10855         switch(vid.renderpath)
10856         {
10857         case RENDERPATH_CGGL:
10858 #ifdef SUPPORTCG
10859                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
10860                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.deluxemaptexture);CHECKCGERROR
10861 #endif
10862                 break;
10863         case RENDERPATH_GL20:
10864                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
10865                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
10866                 break;
10867         case RENDERPATH_GL13:
10868         case RENDERPATH_GL11:
10869                 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10870                 break;
10871         }
10872 }
10873
10874 static void RSurf_BindReflectionForBatch(void)
10875 {
10876         // pick the closest matching water plane and bind textures
10877         int planeindex, vertexindex;
10878         float d, bestd;
10879         vec3_t vert;
10880         const float *v;
10881         r_waterstate_waterplane_t *p, *bestp;
10882         bestd = 0;
10883         bestp = NULL;
10884         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10885         {
10886                 if(p->camera_entity != rsurface.texture->camera_entity)
10887                         continue;
10888                 d = 0;
10889                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10890                 {
10891                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10892                         d += fabs(PlaneDiff(vert, &p->plane));
10893                 }
10894                 if (bestd > d || !bestp)
10895                 {
10896                         bestd = d;
10897                         bestp = p;
10898                 }
10899         }
10900         switch(vid.renderpath)
10901         {
10902         case RENDERPATH_CGGL:
10903 #ifdef SUPPORTCG
10904                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10905                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10906                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10907 #endif
10908                 break;
10909         case RENDERPATH_GL20:
10910                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10911                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10912                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10913                 break;
10914         case RENDERPATH_GL13:
10915         case RENDERPATH_GL11:
10916                 break;
10917         }
10918 }
10919
10920 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10921 {
10922         int i;
10923         for (i = 0;i < rsurface.batchnumvertices;i++)
10924                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10925         rsurface.passcolor4f = rsurface.array_passcolor4f;
10926         rsurface.passcolor4f_vertexbuffer = 0;
10927         rsurface.passcolor4f_bufferoffset = 0;
10928 }
10929
10930 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10931 {
10932         int i;
10933         float f;
10934         const float *v;
10935         const float *c;
10936         float *c2;
10937         if (rsurface.passcolor4f)
10938         {
10939                 // generate color arrays
10940                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10941                 {
10942                         f = RSurf_FogVertex(v);
10943                         c2[0] = c[0] * f;
10944                         c2[1] = c[1] * f;
10945                         c2[2] = c[2] * f;
10946                         c2[3] = c[3];
10947                 }
10948         }
10949         else
10950         {
10951                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10952                 {
10953                         f = RSurf_FogVertex(v);
10954                         c2[0] = f;
10955                         c2[1] = f;
10956                         c2[2] = f;
10957                         c2[3] = 1;
10958                 }
10959         }
10960         rsurface.passcolor4f = rsurface.array_passcolor4f;
10961         rsurface.passcolor4f_vertexbuffer = 0;
10962         rsurface.passcolor4f_bufferoffset = 0;
10963 }
10964
10965 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10966 {
10967         int i;
10968         float f;
10969         const float *v;
10970         const float *c;
10971         float *c2;
10972         if (!rsurface.passcolor4f)
10973                 return;
10974         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10975         {
10976                 f = RSurf_FogVertex(v);
10977                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10978                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10979                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10980                 c2[3] = c[3];
10981         }
10982         rsurface.passcolor4f = rsurface.array_passcolor4f;
10983         rsurface.passcolor4f_vertexbuffer = 0;
10984         rsurface.passcolor4f_bufferoffset = 0;
10985 }
10986
10987 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10988 {
10989         int i;
10990         const float *c;
10991         float *c2;
10992         if (!rsurface.passcolor4f)
10993                 return;
10994         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10995         {
10996                 c2[0] = c[0] * r;
10997                 c2[1] = c[1] * g;
10998                 c2[2] = c[2] * b;
10999                 c2[3] = c[3] * a;
11000         }
11001         rsurface.passcolor4f = rsurface.array_passcolor4f;
11002         rsurface.passcolor4f_vertexbuffer = 0;
11003         rsurface.passcolor4f_bufferoffset = 0;
11004 }
11005
11006 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11007 {
11008         int i;
11009         const float *c;
11010         float *c2;
11011         if (!rsurface.passcolor4f)
11012                 return;
11013         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11014         {
11015                 c2[0] = c[0] + r_refdef.scene.ambient;
11016                 c2[1] = c[1] + r_refdef.scene.ambient;
11017                 c2[2] = c[2] + r_refdef.scene.ambient;
11018                 c2[3] = c[3];
11019         }
11020         rsurface.passcolor4f = rsurface.array_passcolor4f;
11021         rsurface.passcolor4f_vertexbuffer = 0;
11022         rsurface.passcolor4f_bufferoffset = 0;
11023 }
11024
11025 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11026 {
11027         // TODO: optimize
11028         rsurface.passcolor4f = NULL;
11029         rsurface.passcolor4f_vertexbuffer = 0;
11030         rsurface.passcolor4f_bufferoffset = 0;
11031         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11032         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11033         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11034         GL_Color(r, g, b, a);
11035         RSurf_BindLightmapForBatch();
11036         RSurf_DrawBatch();
11037 }
11038
11039 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11040 {
11041         // TODO: optimize applyfog && applycolor case
11042         // just apply fog if necessary, and tint the fog color array if necessary
11043         rsurface.passcolor4f = NULL;
11044         rsurface.passcolor4f_vertexbuffer = 0;
11045         rsurface.passcolor4f_bufferoffset = 0;
11046         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11047         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11048         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11049         GL_Color(r, g, b, a);
11050         RSurf_DrawBatch();
11051 }
11052
11053 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11054 {
11055         // TODO: optimize
11056         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11057         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11058         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11059         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11060         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11061         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11062         GL_Color(r, g, b, a);
11063         RSurf_DrawBatch();
11064 }
11065
11066 static void RSurf_DrawBatch_GL11_ClampColor(void)
11067 {
11068         int i;
11069         const float *c1;
11070         float *c2;
11071         if (!rsurface.passcolor4f)
11072                 return;
11073         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11074         {
11075                 c2[0] = bound(0.0f, c1[0], 1.0f);
11076                 c2[1] = bound(0.0f, c1[1], 1.0f);
11077                 c2[2] = bound(0.0f, c1[2], 1.0f);
11078                 c2[3] = bound(0.0f, c1[3], 1.0f);
11079         }
11080 }
11081
11082 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11083 {
11084         int i;
11085         float f;
11086         float alpha;
11087         const float *v;
11088         const float *n;
11089         float *c;
11090         vec3_t ambientcolor;
11091         vec3_t diffusecolor;
11092         vec3_t lightdir;
11093         // TODO: optimize
11094         // model lighting
11095         VectorCopy(rsurface.modellight_lightdir, lightdir);
11096         f = 0.5f * r_refdef.lightmapintensity;
11097         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11098         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11099         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11100         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11101         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11102         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11103         alpha = *a;
11104         if (VectorLength2(diffusecolor) > 0)
11105         {
11106                 // q3-style directional shading
11107                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
11108                 {
11109                         if ((f = DotProduct(n, lightdir)) > 0)
11110                                 VectorMA(ambientcolor, f, diffusecolor, c);
11111                         else
11112                                 VectorCopy(ambientcolor, c);
11113                         c[3] = alpha;
11114                 }
11115                 *r = 1;
11116                 *g = 1;
11117                 *b = 1;
11118                 *a = 1;
11119                 rsurface.passcolor4f = rsurface.array_passcolor4f;
11120                 rsurface.passcolor4f_vertexbuffer = 0;
11121                 rsurface.passcolor4f_bufferoffset = 0;
11122                 *applycolor = false;
11123         }
11124         else
11125         {
11126                 *r = ambientcolor[0];
11127                 *g = ambientcolor[1];
11128                 *b = ambientcolor[2];
11129                 rsurface.passcolor4f = NULL;
11130                 rsurface.passcolor4f_vertexbuffer = 0;
11131                 rsurface.passcolor4f_bufferoffset = 0;
11132         }
11133 }
11134
11135 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11136 {
11137         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11138         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11139         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11140         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11141         GL_Color(r, g, b, a);
11142         RSurf_DrawBatch();
11143 }
11144
11145 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11146 {
11147         int i;
11148         float f;
11149         const float *v;
11150         float *c;
11151         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11152         {
11153                 f = 1 - RSurf_FogVertex(v);
11154                 c[0] = r;
11155                 c[1] = g;
11156                 c[2] = b;
11157                 c[3] = f * a;
11158         }
11159 }
11160
11161 void RSurf_SetupDepthAndCulling(void)
11162 {
11163         // submodels are biased to avoid z-fighting with world surfaces that they
11164         // may be exactly overlapping (avoids z-fighting artifacts on certain
11165         // doors and things in Quake maps)
11166         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11167         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11168         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11169         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11170 }
11171
11172 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11173 {
11174         // transparent sky would be ridiculous
11175         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11176                 return;
11177         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11178         skyrenderlater = true;
11179         RSurf_SetupDepthAndCulling();
11180         GL_DepthMask(true);
11181         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11182         // skymasking on them, and Quake3 never did sky masking (unlike
11183         // software Quake and software Quake2), so disable the sky masking
11184         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11185         // and skymasking also looks very bad when noclipping outside the
11186         // level, so don't use it then either.
11187         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11188         {
11189                 R_Mesh_ResetTextureState();
11190                 if (skyrendermasked)
11191                 {
11192                         R_SetupShader_DepthOrShadow();
11193                         // depth-only (masking)
11194                         GL_ColorMask(0,0,0,0);
11195                         // just to make sure that braindead drivers don't draw
11196                         // anything despite that colormask...
11197                         GL_BlendFunc(GL_ZERO, GL_ONE);
11198                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11199                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11200                 }
11201                 else
11202                 {
11203                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11204                         // fog sky
11205                         GL_BlendFunc(GL_ONE, GL_ZERO);
11206                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
11207                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11208                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11209                 }
11210                 RSurf_DrawBatch();
11211                 if (skyrendermasked)
11212                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11213         }
11214         R_Mesh_ResetTextureState();
11215         GL_Color(1, 1, 1, 1);
11216 }
11217
11218 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11219 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11220 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11221 {
11222         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11223                 return;
11224         if (prepass)
11225         {
11226                 // render screenspace normalmap to texture
11227                 GL_DepthMask(true);
11228                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
11229                 RSurf_DrawBatch();
11230         }
11231         else if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11232         {
11233                 // render water or distortion background, then blend surface on top
11234                 GL_DepthMask(true);
11235                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, texturenumsurfaces, texturesurfacelist);
11236                 RSurf_BindReflectionForBatch();
11237                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11238                         RSurf_BindLightmapForBatch();
11239                 RSurf_DrawBatch();
11240                 GL_DepthMask(false);
11241                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11242                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11243                         RSurf_BindLightmapForBatch();
11244                 RSurf_DrawBatch();
11245         }
11246         else
11247         {
11248                 // render surface normally
11249                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11250                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
11252                         RSurf_BindReflectionForBatch();
11253                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11254                         RSurf_BindLightmapForBatch();
11255                 RSurf_DrawBatch();
11256         }
11257 }
11258
11259 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11260 {
11261         // OpenGL 1.3 path - anything not completely ancient
11262         qboolean applycolor;
11263         qboolean applyfog;
11264         int layerindex;
11265         const texturelayer_t *layer;
11266         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11267         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11268
11269         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11270         {
11271                 vec4_t layercolor;
11272                 int layertexrgbscale;
11273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11274                 {
11275                         if (layerindex == 0)
11276                                 GL_AlphaTest(true);
11277                         else
11278                         {
11279                                 GL_AlphaTest(false);
11280                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11281                         }
11282                 }
11283                 GL_DepthMask(layer->depthmask && writedepth);
11284                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11285                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11286                 {
11287                         layertexrgbscale = 4;
11288                         VectorScale(layer->color, 0.25f, layercolor);
11289                 }
11290                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11291                 {
11292                         layertexrgbscale = 2;
11293                         VectorScale(layer->color, 0.5f, layercolor);
11294                 }
11295                 else
11296                 {
11297                         layertexrgbscale = 1;
11298                         VectorScale(layer->color, 1.0f, layercolor);
11299                 }
11300                 layercolor[3] = layer->color[3];
11301                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11302                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11303                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11304                 switch (layer->type)
11305                 {
11306                 case TEXTURELAYERTYPE_LITTEXTURE:
11307                         // single-pass lightmapped texture with 2x rgbscale
11308                         R_Mesh_TexBind(0, r_texture_white);
11309                         R_Mesh_TexMatrix(0, NULL);
11310                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11311                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11312                         R_Mesh_TexBind(1, layer->texture);
11313                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11314                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11315                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11316                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11317                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11318                         else if (rsurface.uselightmaptexture)
11319                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11320                         else
11321                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11322                         break;
11323                 case TEXTURELAYERTYPE_TEXTURE:
11324                         // singletexture unlit texture with transparency support
11325                         R_Mesh_TexBind(0, layer->texture);
11326                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11327                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11328                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11329                         R_Mesh_TexBind(1, 0);
11330                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11331                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11332                         break;
11333                 case TEXTURELAYERTYPE_FOG:
11334                         // singletexture fogging
11335                         if (layer->texture)
11336                         {
11337                                 R_Mesh_TexBind(0, layer->texture);
11338                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11339                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11340                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11341                         }
11342                         else
11343                         {
11344                                 R_Mesh_TexBind(0, 0);
11345                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11346                         }
11347                         R_Mesh_TexBind(1, 0);
11348                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11349                         // generate a color array for the fog pass
11350                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11351                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11352                         RSurf_DrawBatch();
11353                         break;
11354                 default:
11355                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11356                 }
11357         }
11358         CHECKGLERROR
11359         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11360         {
11361                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11362                 GL_AlphaTest(false);
11363         }
11364 }
11365
11366 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11367 {
11368         // OpenGL 1.1 - crusty old voodoo path
11369         qboolean applyfog;
11370         int layerindex;
11371         const texturelayer_t *layer;
11372         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11373         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11374
11375         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11376         {
11377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11378                 {
11379                         if (layerindex == 0)
11380                                 GL_AlphaTest(true);
11381                         else
11382                         {
11383                                 GL_AlphaTest(false);
11384                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11385                         }
11386                 }
11387                 GL_DepthMask(layer->depthmask && writedepth);
11388                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11389                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11390                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11391                 switch (layer->type)
11392                 {
11393                 case TEXTURELAYERTYPE_LITTEXTURE:
11394                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11395                         {
11396                                 // two-pass lit texture with 2x rgbscale
11397                                 // first the lightmap pass
11398                                 R_Mesh_TexBind(0, r_texture_white);
11399                                 R_Mesh_TexMatrix(0, NULL);
11400                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11401                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11402                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11403                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11404                                 else if (rsurface.uselightmaptexture)
11405                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11406                                 else
11407                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11408                                 // then apply the texture to it
11409                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11410                                 R_Mesh_TexBind(0, layer->texture);
11411                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11412                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11413                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11414                                 RSurf_DrawBatch_GL11_Unlit(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);
11415                         }
11416                         else
11417                         {
11418                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11419                                 R_Mesh_TexBind(0, layer->texture);
11420                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11421                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11422                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11423                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11424                                         RSurf_DrawBatch_GL11_VertexShade(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);
11425                                 else
11426                                         RSurf_DrawBatch_GL11_VertexColor(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);
11427                         }
11428                         break;
11429                 case TEXTURELAYERTYPE_TEXTURE:
11430                         // singletexture unlit texture with transparency support
11431                         R_Mesh_TexBind(0, layer->texture);
11432                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11433                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11434                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11435                         RSurf_DrawBatch_GL11_Unlit(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);
11436                         break;
11437                 case TEXTURELAYERTYPE_FOG:
11438                         // singletexture fogging
11439                         if (layer->texture)
11440                         {
11441                                 R_Mesh_TexBind(0, layer->texture);
11442                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11443                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11444                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11445                         }
11446                         else
11447                         {
11448                                 R_Mesh_TexBind(0, 0);
11449                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11450                         }
11451                         // generate a color array for the fog pass
11452                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11453                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11454                         RSurf_DrawBatch();
11455                         break;
11456                 default:
11457                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11458                 }
11459         }
11460         CHECKGLERROR
11461         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11462         {
11463                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11464                 GL_AlphaTest(false);
11465         }
11466 }
11467
11468 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11469 {
11470         int vi;
11471         int j;
11472         r_vertexgeneric_t *batchvertex;
11473         float c[4];
11474
11475         GL_AlphaTest(false);
11476         R_Mesh_ResetTextureState();
11477         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11478
11479         if(rsurface.texture && rsurface.texture->currentskinframe)
11480         {
11481                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11482                 c[3] *= rsurface.texture->currentalpha;
11483         }
11484         else
11485         {
11486                 c[0] = 1;
11487                 c[1] = 0;
11488                 c[2] = 1;
11489                 c[3] = 1;
11490         }
11491
11492         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11493         {
11494                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11495                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11496                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11497         }
11498
11499         // brighten it up (as texture value 127 means "unlit")
11500         c[0] *= 2 * r_refdef.view.colorscale;
11501         c[1] *= 2 * r_refdef.view.colorscale;
11502         c[2] *= 2 * r_refdef.view.colorscale;
11503
11504         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11505                 c[3] *= r_wateralpha.value;
11506
11507         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11508         {
11509                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11510                 GL_DepthMask(false);
11511         }
11512         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11513         {
11514                 GL_BlendFunc(GL_ONE, GL_ONE);
11515                 GL_DepthMask(false);
11516         }
11517         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11518         {
11519                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11520                 GL_DepthMask(false);
11521         }
11522         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11523         {
11524                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11525                 GL_DepthMask(false);
11526         }
11527         else
11528         {
11529                 GL_BlendFunc(GL_ONE, GL_ZERO);
11530                 GL_DepthMask(writedepth);
11531         }
11532
11533         if (r_showsurfaces.integer == 3)
11534         {
11535                 rsurface.passcolor4f = NULL;
11536
11537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11538                 {
11539                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11540
11541                         rsurface.passcolor4f = NULL;
11542                         rsurface.passcolor4f_vertexbuffer = 0;
11543                         rsurface.passcolor4f_bufferoffset = 0;
11544                 }
11545                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11546                 {
11547                         qboolean applycolor = true;
11548                         float one = 1.0;
11549
11550                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11551
11552                         r_refdef.lightmapintensity = 1;
11553                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11554                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11555                 }
11556                 else
11557                 {
11558                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11559
11560                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11561                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11562                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11563                 }
11564
11565                 if(!rsurface.passcolor4f)
11566                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11567
11568                 RSurf_DrawBatch_GL11_ApplyAmbient();
11569                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11570                 if(r_refdef.fogenabled)
11571                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11572                 RSurf_DrawBatch_GL11_ClampColor();
11573
11574                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11575                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11576                 RSurf_DrawBatch();
11577         }
11578         else if (!r_refdef.view.showdebug)
11579         {
11580                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11581                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11582                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11583                 {
11584                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11585                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
11586                 }
11587                 R_Mesh_PrepareVertices_Generic_Unlock();
11588                 RSurf_DrawBatch();
11589         }
11590         else if (r_showsurfaces.integer == 4)
11591         {
11592                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11593                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11594                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11595                 {
11596                         unsigned char c = vi << 3;
11597                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11598                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
11599                 }
11600                 R_Mesh_PrepareVertices_Generic_Unlock();
11601                 RSurf_DrawBatch();
11602         }
11603         else if (r_showsurfaces.integer == 2)
11604         {
11605                 const int *e;
11606                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11607                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11608                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11609                 {
11610                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
11611                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11612                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11613                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11614                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
11615                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
11616                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
11617                 }
11618                 R_Mesh_PrepareVertices_Generic_Unlock();
11619                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11620         }
11621         else
11622         {
11623                 int texturesurfaceindex;
11624                 int k;
11625                 const msurface_t *surface;
11626                 unsigned char surfacecolor4ub[4];
11627                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11628                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11629                 vi = 0;
11630                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11631                 {
11632                         surface = texturesurfacelist[texturesurfaceindex];
11633                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11634                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
11635                         for (j = 0;j < surface->num_vertices;j++)
11636                         {
11637                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11638                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
11639                                 vi++;
11640                         }
11641                 }
11642                 R_Mesh_PrepareVertices_Generic_Unlock();
11643                 RSurf_DrawBatch();
11644         }
11645 }
11646
11647 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11648 {
11649         CHECKGLERROR
11650         RSurf_SetupDepthAndCulling();
11651         if (r_showsurfaces.integer)
11652         {
11653                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11654                 return;
11655         }
11656         switch (vid.renderpath)
11657         {
11658         case RENDERPATH_GL20:
11659         case RENDERPATH_CGGL:
11660                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11661                 break;
11662         case RENDERPATH_GL13:
11663                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11664                 break;
11665         case RENDERPATH_GL11:
11666                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11667                 break;
11668         }
11669         CHECKGLERROR
11670 }
11671
11672 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11673 {
11674         CHECKGLERROR
11675         RSurf_SetupDepthAndCulling();
11676         if (r_showsurfaces.integer)
11677         {
11678                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11679                 return;
11680         }
11681         switch (vid.renderpath)
11682         {
11683         case RENDERPATH_GL20:
11684         case RENDERPATH_CGGL:
11685                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11686                 break;
11687         case RENDERPATH_GL13:
11688                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11689                 break;
11690         case RENDERPATH_GL11:
11691                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11692                 break;
11693         }
11694         CHECKGLERROR
11695 }
11696
11697 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11698 {
11699         int i, j;
11700         int texturenumsurfaces, endsurface;
11701         texture_t *texture;
11702         const msurface_t *surface;
11703 #define MAXBATCH_TRANSPARENTSURFACES 256
11704         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11705
11706         // if the model is static it doesn't matter what value we give for
11707         // wantnormals and wanttangents, so this logic uses only rules applicable
11708         // to a model, knowing that they are meaningless otherwise
11709         if (ent == r_refdef.scene.worldentity)
11710                 RSurf_ActiveWorldEntity();
11711         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11712                 RSurf_ActiveModelEntity(ent, false, false, false);
11713         else
11714         {
11715                 switch (vid.renderpath)
11716                 {
11717                 case RENDERPATH_GL20:
11718                 case RENDERPATH_CGGL:
11719                         RSurf_ActiveModelEntity(ent, true, true, false);
11720                         break;
11721                 case RENDERPATH_GL13:
11722                 case RENDERPATH_GL11:
11723                         RSurf_ActiveModelEntity(ent, true, false, false);
11724                         break;
11725                 }
11726         }
11727
11728         if (r_transparentdepthmasking.integer)
11729         {
11730                 qboolean setup = false;
11731                 for (i = 0;i < numsurfaces;i = j)
11732                 {
11733                         j = i + 1;
11734                         surface = rsurface.modelsurfaces + surfacelist[i];
11735                         texture = surface->texture;
11736                         rsurface.texture = R_GetCurrentTexture(texture);
11737                         rsurface.lightmaptexture = NULL;
11738                         rsurface.deluxemaptexture = NULL;
11739                         rsurface.uselightmaptexture = false;
11740                         // scan ahead until we find a different texture
11741                         endsurface = min(i + 1024, numsurfaces);
11742                         texturenumsurfaces = 0;
11743                         texturesurfacelist[texturenumsurfaces++] = surface;
11744                         for (;j < endsurface;j++)
11745                         {
11746                                 surface = rsurface.modelsurfaces + surfacelist[j];
11747                                 if (texture != surface->texture)
11748                                         break;
11749                                 texturesurfacelist[texturenumsurfaces++] = surface;
11750                         }
11751                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11752                                 continue;
11753                         // render the range of surfaces as depth
11754                         if (!setup)
11755                         {
11756                                 setup = true;
11757                                 GL_ColorMask(0,0,0,0);
11758                                 GL_Color(1,1,1,1);
11759                                 GL_DepthTest(true);
11760                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11761                                 GL_DepthMask(true);
11762                                 GL_AlphaTest(false);
11763                                 R_Mesh_ResetTextureState();
11764                                 R_SetupShader_DepthOrShadow();
11765                         }
11766                         RSurf_SetupDepthAndCulling();
11767                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11768                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11769                         RSurf_DrawBatch();
11770                 }
11771                 if (setup)
11772                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11773         }
11774
11775         for (i = 0;i < numsurfaces;i = j)
11776         {
11777                 j = i + 1;
11778                 surface = rsurface.modelsurfaces + surfacelist[i];
11779                 texture = surface->texture;
11780                 rsurface.texture = R_GetCurrentTexture(texture);
11781                 rsurface.lightmaptexture = surface->lightmaptexture;
11782                 rsurface.deluxemaptexture = surface->deluxemaptexture;
11783                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11784                 // scan ahead until we find a different texture
11785                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11786                 texturenumsurfaces = 0;
11787                 texturesurfacelist[texturenumsurfaces++] = surface;
11788                 for (;j < endsurface;j++)
11789                 {
11790                         surface = rsurface.modelsurfaces + surfacelist[j];
11791                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11792                                 break;
11793                         texturesurfacelist[texturenumsurfaces++] = surface;
11794                 }
11795                 // render the range of surfaces
11796                 if (ent == r_refdef.scene.worldentity)
11797                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11798                 else
11799                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11800         }
11801         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11802         GL_AlphaTest(false);
11803 }
11804
11805 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11806 {
11807         // transparent surfaces get pushed off into the transparent queue
11808         int surfacelistindex;
11809         const msurface_t *surface;
11810         vec3_t tempcenter, center;
11811         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11812         {
11813                 surface = texturesurfacelist[surfacelistindex];
11814                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11815                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11816                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11817                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11818                 if (queueentity->transparent_offset) // transparent offset
11819                 {
11820                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11821                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11822                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11823                 }
11824                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11825         }
11826 }
11827
11828 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11829 {
11830         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11831                 return;
11832         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11833                 return;
11834         RSurf_SetupDepthAndCulling();
11835         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11836         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11837         RSurf_DrawBatch();
11838 }
11839
11840 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11841 {
11842         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11843         CHECKGLERROR
11844         if (depthonly)
11845                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11846         else if (prepass)
11847         {
11848                 if (!rsurface.texture->currentnumlayers)
11849                         return;
11850                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11851                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11852                 else
11853                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11854         }
11855         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11856                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11857         else if (!rsurface.texture->currentnumlayers)
11858                 return;
11859         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11860         {
11861                 // in the deferred case, transparent surfaces were queued during prepass
11862                 if (!r_shadow_usingdeferredprepass)
11863                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11864         }
11865         else
11866         {
11867                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11868                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11869         }
11870         CHECKGLERROR
11871 }
11872
11873 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11874 {
11875         int i, j;
11876         texture_t *texture;
11877         // break the surface list down into batches by texture and use of lightmapping
11878         for (i = 0;i < numsurfaces;i = j)
11879         {
11880                 j = i + 1;
11881                 // texture is the base texture pointer, rsurface.texture is the
11882                 // current frame/skin the texture is directing us to use (for example
11883                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11884                 // use skin 1 instead)
11885                 texture = surfacelist[i]->texture;
11886                 rsurface.texture = R_GetCurrentTexture(texture);
11887                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11888                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11889                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11890                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11891                 {
11892                         // if this texture is not the kind we want, skip ahead to the next one
11893                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11894                                 ;
11895                         continue;
11896                 }
11897                 // simply scan ahead until we find a different texture or lightmap state
11898                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11899                         ;
11900                 // render the range of surfaces
11901                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11902         }
11903 }
11904
11905 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
11906 {
11907         CHECKGLERROR
11908         if (depthonly)
11909                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11910         else if (prepass)
11911         {
11912                 if (!rsurface.texture->currentnumlayers)
11913                         return;
11914                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11915                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11916                 else
11917                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11918         }
11919         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11920                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11921         else if (!rsurface.texture->currentnumlayers)
11922                 return;
11923         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11924         {
11925                 // in the deferred case, transparent surfaces were queued during prepass
11926                 if (!r_shadow_usingdeferredprepass)
11927                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11928         }
11929         else
11930         {
11931                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11932                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11933         }
11934         CHECKGLERROR
11935 }
11936
11937 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11938 {
11939         int i, j;
11940         texture_t *texture;
11941         // break the surface list down into batches by texture and use of lightmapping
11942         for (i = 0;i < numsurfaces;i = j)
11943         {
11944                 j = i + 1;
11945                 // texture is the base texture pointer, rsurface.texture is the
11946                 // current frame/skin the texture is directing us to use (for example
11947                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11948                 // use skin 1 instead)
11949                 texture = surfacelist[i]->texture;
11950                 rsurface.texture = R_GetCurrentTexture(texture);
11951                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11952                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11953                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11954                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11955                 {
11956                         // if this texture is not the kind we want, skip ahead to the next one
11957                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11958                                 ;
11959                         continue;
11960                 }
11961                 // simply scan ahead until we find a different texture or lightmap state
11962                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11963                         ;
11964                 // render the range of surfaces
11965                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
11966         }
11967 }
11968
11969 float locboxvertex3f[6*4*3] =
11970 {
11971         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11972         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11973         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11974         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11975         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11976         1,0,0, 0,0,0, 0,1,0, 1,1,0
11977 };
11978
11979 unsigned short locboxelements[6*2*3] =
11980 {
11981          0, 1, 2, 0, 2, 3,
11982          4, 5, 6, 4, 6, 7,
11983          8, 9,10, 8,10,11,
11984         12,13,14, 12,14,15,
11985         16,17,18, 16,18,19,
11986         20,21,22, 20,22,23
11987 };
11988
11989 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11990 {
11991         int i, j;
11992         cl_locnode_t *loc = (cl_locnode_t *)ent;
11993         vec3_t mins, size;
11994         float vertex3f[6*4*3];
11995         CHECKGLERROR
11996         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11997         GL_DepthMask(false);
11998         GL_DepthRange(0, 1);
11999         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12000         GL_DepthTest(true);
12001         GL_CullFace(GL_NONE);
12002         R_EntityMatrix(&identitymatrix);
12003
12004         R_Mesh_ResetTextureState();
12005
12006         i = surfacelist[0];
12007         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12008                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12009                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12010                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12011
12012         if (VectorCompare(loc->mins, loc->maxs))
12013         {
12014                 VectorSet(size, 2, 2, 2);
12015                 VectorMA(loc->mins, -0.5f, size, mins);
12016         }
12017         else
12018         {
12019                 VectorCopy(loc->mins, mins);
12020                 VectorSubtract(loc->maxs, loc->mins, size);
12021         }
12022
12023         for (i = 0;i < 6*4*3;)
12024                 for (j = 0;j < 3;j++, i++)
12025                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12026
12027         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12028         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12029         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12030 }
12031
12032 void R_DrawLocs(void)
12033 {
12034         int index;
12035         cl_locnode_t *loc, *nearestloc;
12036         vec3_t center;
12037         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12038         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12039         {
12040                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12041                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12042         }
12043 }
12044
12045 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12046 {
12047         if (decalsystem->decals)
12048                 Mem_Free(decalsystem->decals);
12049         memset(decalsystem, 0, sizeof(*decalsystem));
12050 }
12051
12052 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)
12053 {
12054         tridecal_t *decal;
12055         tridecal_t *decals;
12056         int i;
12057
12058         // expand or initialize the system
12059         if (decalsystem->maxdecals <= decalsystem->numdecals)
12060         {
12061                 decalsystem_t old = *decalsystem;
12062                 qboolean useshortelements;
12063                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12064                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12065                 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)));
12066                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12067                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12068                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12069                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12070                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12071                 if (decalsystem->numdecals)
12072                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12073                 if (old.decals)
12074                         Mem_Free(old.decals);
12075                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12076                         decalsystem->element3i[i] = i;
12077                 if (useshortelements)
12078                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12079                                 decalsystem->element3s[i] = i;
12080         }
12081
12082         // grab a decal and search for another free slot for the next one
12083         decals = decalsystem->decals;
12084         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12085         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12086                 ;
12087         decalsystem->freedecal = i;
12088         if (decalsystem->numdecals <= i)
12089                 decalsystem->numdecals = i + 1;
12090
12091         // initialize the decal
12092         decal->lived = 0;
12093         decal->triangleindex = triangleindex;
12094         decal->surfaceindex = surfaceindex;
12095         decal->decalsequence = decalsequence;
12096         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12097         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12098         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12099         decal->color4ub[0][3] = 255;
12100         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12101         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12102         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12103         decal->color4ub[1][3] = 255;
12104         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12105         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12106         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12107         decal->color4ub[2][3] = 255;
12108         decal->vertex3f[0][0] = v0[0];
12109         decal->vertex3f[0][1] = v0[1];
12110         decal->vertex3f[0][2] = v0[2];
12111         decal->vertex3f[1][0] = v1[0];
12112         decal->vertex3f[1][1] = v1[1];
12113         decal->vertex3f[1][2] = v1[2];
12114         decal->vertex3f[2][0] = v2[0];
12115         decal->vertex3f[2][1] = v2[1];
12116         decal->vertex3f[2][2] = v2[2];
12117         decal->texcoord2f[0][0] = t0[0];
12118         decal->texcoord2f[0][1] = t0[1];
12119         decal->texcoord2f[1][0] = t1[0];
12120         decal->texcoord2f[1][1] = t1[1];
12121         decal->texcoord2f[2][0] = t2[0];
12122         decal->texcoord2f[2][1] = t2[1];
12123 }
12124
12125 extern cvar_t cl_decals_bias;
12126 extern cvar_t cl_decals_models;
12127 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12128 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)
12129 {
12130         matrix4x4_t projection;
12131         decalsystem_t *decalsystem;
12132         qboolean dynamic;
12133         dp_model_t *model;
12134         const float *vertex3f;
12135         const msurface_t *surface;
12136         const msurface_t *surfaces;
12137         const int *surfacelist;
12138         const texture_t *texture;
12139         int numtriangles;
12140         int numsurfacelist;
12141         int surfacelistindex;
12142         int surfaceindex;
12143         int triangleindex;
12144         int cornerindex;
12145         int index;
12146         int numpoints;
12147         const int *e;
12148         float localorigin[3];
12149         float localnormal[3];
12150         float localmins[3];
12151         float localmaxs[3];
12152         float localsize;
12153         float v[9][3];
12154         float tc[9][2];
12155         float c[9][4];
12156         //float normal[3];
12157         float planes[6][4];
12158         float f;
12159         float points[2][9][3];
12160         float angles[3];
12161         float temp[3];
12162
12163         decalsystem = &ent->decalsystem;
12164         model = ent->model;
12165         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12166         {
12167                 R_DecalSystem_Reset(&ent->decalsystem);
12168                 return;
12169         }
12170
12171         if (!model->brush.data_nodes && !cl_decals_models.integer)
12172         {
12173                 if (decalsystem->model)
12174                         R_DecalSystem_Reset(decalsystem);
12175                 return;
12176         }
12177
12178         if (decalsystem->model != model)
12179                 R_DecalSystem_Reset(decalsystem);
12180         decalsystem->model = model;
12181
12182         RSurf_ActiveModelEntity(ent, false, false, false);
12183
12184         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12185         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12186         VectorNormalize(localnormal);
12187         localsize = worldsize*rsurface.inversematrixscale;
12188         localmins[0] = localorigin[0] - localsize;
12189         localmins[1] = localorigin[1] - localsize;
12190         localmins[2] = localorigin[2] - localsize;
12191         localmaxs[0] = localorigin[0] + localsize;
12192         localmaxs[1] = localorigin[1] + localsize;
12193         localmaxs[2] = localorigin[2] + localsize;
12194
12195         //VectorCopy(localnormal, planes[4]);
12196         //VectorVectors(planes[4], planes[2], planes[0]);
12197         AnglesFromVectors(angles, localnormal, NULL, false);
12198         AngleVectors(angles, planes[0], planes[2], planes[4]);
12199         VectorNegate(planes[0], planes[1]);
12200         VectorNegate(planes[2], planes[3]);
12201         VectorNegate(planes[4], planes[5]);
12202         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12203         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12204         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12205         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12206         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12207         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12208
12209 #if 1
12210 // works
12211 {
12212         matrix4x4_t forwardprojection;
12213         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12214         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12215 }
12216 #else
12217 // broken
12218 {
12219         float projectionvector[4][3];
12220         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12221         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12222         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12223         projectionvector[0][0] = planes[0][0] * ilocalsize;
12224         projectionvector[0][1] = planes[1][0] * ilocalsize;
12225         projectionvector[0][2] = planes[2][0] * ilocalsize;
12226         projectionvector[1][0] = planes[0][1] * ilocalsize;
12227         projectionvector[1][1] = planes[1][1] * ilocalsize;
12228         projectionvector[1][2] = planes[2][1] * ilocalsize;
12229         projectionvector[2][0] = planes[0][2] * ilocalsize;
12230         projectionvector[2][1] = planes[1][2] * ilocalsize;
12231         projectionvector[2][2] = planes[2][2] * ilocalsize;
12232         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12233         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12234         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12235         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12236 }
12237 #endif
12238
12239         dynamic = model->surfmesh.isanimated;
12240         vertex3f = rsurface.modelvertex3f;
12241         numsurfacelist = model->nummodelsurfaces;
12242         surfacelist = model->sortedmodelsurfaces;
12243         surfaces = model->data_surfaces;
12244         for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12245         {
12246                 surfaceindex = surfacelist[surfacelistindex];
12247                 surface = surfaces + surfaceindex;
12248                 // check cull box first because it rejects more than any other check
12249                 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12250                         continue;
12251                 // skip transparent surfaces
12252                 texture = surface->texture;
12253                 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12254                         continue;
12255                 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12256                         continue;
12257                 numtriangles = surface->num_triangles;
12258                 for (triangleindex = 0, e = model->surfmesh.data_element3i + 3*surface->num_firsttriangle;triangleindex < numtriangles;triangleindex++, e += 3)
12259                 {
12260                         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12261                         {
12262                                 index = 3*e[cornerindex];
12263                                 VectorCopy(vertex3f + index, v[cornerindex]);
12264                         }
12265                         // cull backfaces
12266                         //TriangleNormal(v[0], v[1], v[2], normal);
12267                         //if (DotProduct(normal, localnormal) < 0.0f)
12268                         //      continue;
12269                         // clip by each of the box planes formed from the projection matrix
12270                         // if anything survives, we emit the decal
12271                         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]);
12272                         if (numpoints < 3)
12273                                 continue;
12274                         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]);
12275                         if (numpoints < 3)
12276                                 continue;
12277                         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]);
12278                         if (numpoints < 3)
12279                                 continue;
12280                         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]);
12281                         if (numpoints < 3)
12282                                 continue;
12283                         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]);
12284                         if (numpoints < 3)
12285                                 continue;
12286                         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]);
12287                         if (numpoints < 3)
12288                                 continue;
12289                         // some part of the triangle survived, so we have to accept it...
12290                         if (dynamic)
12291                         {
12292                                 // dynamic always uses the original triangle
12293                                 numpoints = 3;
12294                                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12295                                 {
12296                                         index = 3*e[cornerindex];
12297                                         VectorCopy(vertex3f + index, v[cornerindex]);
12298                                 }
12299                         }
12300                         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12301                         {
12302                                 // convert vertex positions to texcoords
12303                                 Matrix4x4_Transform(&projection, v[cornerindex], temp);
12304                                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12305                                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12306                                 // calculate distance fade from the projection origin
12307                                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12308                                 f = bound(0.0f, f, 1.0f);
12309                                 c[cornerindex][0] = r * f;
12310                                 c[cornerindex][1] = g * f;
12311                                 c[cornerindex][2] = b * f;
12312                                 c[cornerindex][3] = 1.0f;
12313                                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12314                         }
12315                         if (dynamic)
12316                                 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);
12317                         else
12318                                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12319                                         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);
12320                 }
12321         }
12322 }
12323
12324 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12325 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)
12326 {
12327         int renderentityindex;
12328         float worldmins[3];
12329         float worldmaxs[3];
12330         entity_render_t *ent;
12331
12332         if (!cl_decals_newsystem.integer)
12333                 return;
12334
12335         worldmins[0] = worldorigin[0] - worldsize;
12336         worldmins[1] = worldorigin[1] - worldsize;
12337         worldmins[2] = worldorigin[2] - worldsize;
12338         worldmaxs[0] = worldorigin[0] + worldsize;
12339         worldmaxs[1] = worldorigin[1] + worldsize;
12340         worldmaxs[2] = worldorigin[2] + worldsize;
12341
12342         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12343
12344         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12345         {
12346                 ent = r_refdef.scene.entities[renderentityindex];
12347                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12348                         continue;
12349
12350                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12351         }
12352 }
12353
12354 typedef struct r_decalsystem_splatqueue_s
12355 {
12356         vec3_t worldorigin;
12357         vec3_t worldnormal;
12358         float color[4];
12359         float tcrange[4];
12360         float worldsize;
12361         int decalsequence;
12362 }
12363 r_decalsystem_splatqueue_t;
12364
12365 int r_decalsystem_numqueued = 0;
12366 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12367
12368 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)
12369 {
12370         r_decalsystem_splatqueue_t *queue;
12371
12372         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12373                 return;
12374
12375         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12376         VectorCopy(worldorigin, queue->worldorigin);
12377         VectorCopy(worldnormal, queue->worldnormal);
12378         Vector4Set(queue->color, r, g, b, a);
12379         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12380         queue->worldsize = worldsize;
12381         queue->decalsequence = cl.decalsequence++;
12382 }
12383
12384 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12385 {
12386         int i;
12387         r_decalsystem_splatqueue_t *queue;
12388
12389         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12390                 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);
12391         r_decalsystem_numqueued = 0;
12392 }
12393
12394 extern cvar_t cl_decals_max;
12395 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12396 {
12397         int i;
12398         decalsystem_t *decalsystem = &ent->decalsystem;
12399         int numdecals;
12400         int killsequence;
12401         tridecal_t *decal;
12402         float frametime;
12403         float lifetime;
12404
12405         if (!decalsystem->numdecals)
12406                 return;
12407
12408         if (r_showsurfaces.integer)
12409                 return;
12410
12411         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12412         {
12413                 R_DecalSystem_Reset(decalsystem);
12414                 return;
12415         }
12416
12417         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12418         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12419
12420         if (decalsystem->lastupdatetime)
12421                 frametime = (cl.time - decalsystem->lastupdatetime);
12422         else
12423                 frametime = 0;
12424         decalsystem->lastupdatetime = cl.time;
12425         decal = decalsystem->decals;
12426         numdecals = decalsystem->numdecals;
12427
12428         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12429         {
12430                 if (decal->color4ub[0][3])
12431                 {
12432                         decal->lived += frametime;
12433                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12434                         {
12435                                 memset(decal, 0, sizeof(*decal));
12436                                 if (decalsystem->freedecal > i)
12437                                         decalsystem->freedecal = i;
12438                         }
12439                 }
12440         }
12441         decal = decalsystem->decals;
12442         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12443                 numdecals--;
12444
12445         // collapse the array by shuffling the tail decals into the gaps
12446         for (;;)
12447         {
12448                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12449                         decalsystem->freedecal++;
12450                 if (decalsystem->freedecal == numdecals)
12451                         break;
12452                 decal[decalsystem->freedecal] = decal[--numdecals];
12453         }
12454
12455         decalsystem->numdecals = numdecals;
12456
12457         if (numdecals <= 0)
12458         {
12459                 // if there are no decals left, reset decalsystem
12460                 R_DecalSystem_Reset(decalsystem);
12461         }
12462 }
12463
12464 extern skinframe_t *decalskinframe;
12465 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12466 {
12467         int i;
12468         decalsystem_t *decalsystem = &ent->decalsystem;
12469         int numdecals;
12470         tridecal_t *decal;
12471         float faderate;
12472         float alpha;
12473         float *v3f;
12474         float *c4f;
12475         float *t2f;
12476         const int *e;
12477         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12478         int numtris = 0;
12479
12480         numdecals = decalsystem->numdecals;
12481         if (!numdecals)
12482                 return;
12483
12484         if (r_showsurfaces.integer)
12485                 return;
12486
12487         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12488         {
12489                 R_DecalSystem_Reset(decalsystem);
12490                 return;
12491         }
12492
12493         // if the model is static it doesn't matter what value we give for
12494         // wantnormals and wanttangents, so this logic uses only rules applicable
12495         // to a model, knowing that they are meaningless otherwise
12496         if (ent == r_refdef.scene.worldentity)
12497                 RSurf_ActiveWorldEntity();
12498         else
12499                 RSurf_ActiveModelEntity(ent, false, false, false);
12500
12501         decalsystem->lastupdatetime = cl.time;
12502         decal = decalsystem->decals;
12503
12504         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12505
12506         // update vertex positions for animated models
12507         v3f = decalsystem->vertex3f;
12508         c4f = decalsystem->color4f;
12509         t2f = decalsystem->texcoord2f;
12510         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12511         {
12512                 if (!decal->color4ub[0][3])
12513                         continue;
12514
12515                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12516                         continue;
12517
12518                 // update color values for fading decals
12519                 if (decal->lived >= cl_decals_time.value)
12520                 {
12521                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12522                         alpha *= (1.0f/255.0f);
12523                 }
12524                 else
12525                         alpha = 1.0f/255.0f;
12526
12527                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12528                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12529                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12530                 c4f[ 3] = 1;
12531                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12532                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12533                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12534                 c4f[ 7] = 1;
12535                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12536                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12537                 c4f[10] = decal->color4ub[2][2] * alpha;
12538                 c4f[11] = 1;
12539
12540                 t2f[0] = decal->texcoord2f[0][0];
12541                 t2f[1] = decal->texcoord2f[0][1];
12542                 t2f[2] = decal->texcoord2f[1][0];
12543                 t2f[3] = decal->texcoord2f[1][1];
12544                 t2f[4] = decal->texcoord2f[2][0];
12545                 t2f[5] = decal->texcoord2f[2][1];
12546
12547                 // update vertex positions for animated models
12548                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12549                 {
12550                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12551                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
12552                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
12553                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
12554                 }
12555                 else
12556                 {
12557                         VectorCopy(decal->vertex3f[0], v3f);
12558                         VectorCopy(decal->vertex3f[1], v3f + 3);
12559                         VectorCopy(decal->vertex3f[2], v3f + 6);
12560                 }
12561
12562                 if (r_refdef.fogenabled)
12563                 {
12564                         alpha = RSurf_FogVertex(v3f);
12565                         VectorScale(c4f, alpha, c4f);
12566                         alpha = RSurf_FogVertex(v3f + 3);
12567                         VectorScale(c4f + 4, alpha, c4f + 4);
12568                         alpha = RSurf_FogVertex(v3f + 6);
12569                         VectorScale(c4f + 8, alpha, c4f + 8);
12570                 }
12571
12572                 v3f += 9;
12573                 c4f += 12;
12574                 t2f += 6;
12575                 numtris++;
12576         }
12577
12578         if (numtris > 0)
12579         {
12580                 r_refdef.stats.drawndecals += numtris;
12581
12582                 // now render the decals all at once
12583                 // (this assumes they all use one particle font texture!)
12584                 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);
12585                 R_Mesh_ResetTextureState();
12586                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12587                 GL_DepthMask(false);
12588                 GL_DepthRange(0, 1);
12589                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12590                 GL_DepthTest(true);
12591                 GL_CullFace(GL_NONE);
12592                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12593                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12594                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12595         }
12596 }
12597
12598 static void R_DrawModelDecals(void)
12599 {
12600         int i, numdecals;
12601
12602         // fade faster when there are too many decals
12603         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12604         for (i = 0;i < r_refdef.scene.numentities;i++)
12605                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12606
12607         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12608         for (i = 0;i < r_refdef.scene.numentities;i++)
12609                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12610                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12611
12612         R_DecalSystem_ApplySplatEntitiesQueue();
12613
12614         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12615         for (i = 0;i < r_refdef.scene.numentities;i++)
12616                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12617
12618         r_refdef.stats.totaldecals += numdecals;
12619
12620         if (r_showsurfaces.integer)
12621                 return;
12622
12623         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12624
12625         for (i = 0;i < r_refdef.scene.numentities;i++)
12626         {
12627                 if (!r_refdef.viewcache.entityvisible[i])
12628                         continue;
12629                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12630                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12631         }
12632 }
12633
12634 extern cvar_t mod_collision_bih;
12635 void R_DrawDebugModel(void)
12636 {
12637         entity_render_t *ent = rsurface.entity;
12638         int i, j, k, l, flagsmask;
12639         const msurface_t *surface;
12640         dp_model_t *model = ent->model;
12641         vec3_t v;
12642
12643         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12644
12645         R_Mesh_ResetTextureState();
12646         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12647         GL_DepthRange(0, 1);
12648         GL_DepthTest(!r_showdisabledepthtest.integer);
12649         GL_DepthMask(false);
12650         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12651
12652         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12653         {
12654                 int triangleindex;
12655                 int bihleafindex;
12656                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12657                 const q3mbrush_t *brush;
12658                 const bih_t *bih = &model->collision_bih;
12659                 const bih_leaf_t *bihleaf;
12660                 float vertex3f[3][3];
12661                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12662                 cullbox = false;
12663                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12664                 {
12665                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12666                                 continue;
12667                         switch (bihleaf->type)
12668                         {
12669                         case BIH_BRUSH:
12670                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12671                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12672                                 {
12673                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12674                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12675                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12676                                 }
12677                                 break;
12678                         case BIH_COLLISIONTRIANGLE:
12679                                 triangleindex = bihleaf->itemindex;
12680                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12681                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12682                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12683                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12684                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12685                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12686                                 break;
12687                         case BIH_RENDERTRIANGLE:
12688                                 triangleindex = bihleaf->itemindex;
12689                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12690                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12691                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12692                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12693                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12694                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12695                                 break;
12696                         }
12697                 }
12698         }
12699
12700         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12701
12702         if (r_showtris.integer || r_shownormals.integer)
12703         {
12704                 if (r_showdisabledepthtest.integer)
12705                 {
12706                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12707                         GL_DepthMask(false);
12708                 }
12709                 else
12710                 {
12711                         GL_BlendFunc(GL_ONE, GL_ZERO);
12712                         GL_DepthMask(true);
12713                 }
12714                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12715                 {
12716                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12717                                 continue;
12718                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12719                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12720                         {
12721                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12722                                 if (r_showtris.value > 0)
12723                                 {
12724                                         if (!rsurface.texture->currentlayers->depthmask)
12725                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12726                                         else if (ent == r_refdef.scene.worldentity)
12727                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12728                                         else
12729                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12730                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12731                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12732                                         RSurf_DrawBatch();
12733                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12734                                         CHECKGLERROR
12735                                 }
12736                                 if (r_shownormals.value < 0)
12737                                 {
12738                                         qglBegin(GL_LINES);
12739                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12740                                         {
12741                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12742                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12743                                                 qglVertex3f(v[0], v[1], v[2]);
12744                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12745                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12746                                                 qglVertex3f(v[0], v[1], v[2]);
12747                                         }
12748                                         qglEnd();
12749                                         CHECKGLERROR
12750                                 }
12751                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12752                                 {
12753                                         qglBegin(GL_LINES);
12754                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12755                                         {
12756                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12757                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12758                                                 qglVertex3f(v[0], v[1], v[2]);
12759                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12760                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12761                                                 qglVertex3f(v[0], v[1], v[2]);
12762                                         }
12763                                         qglEnd();
12764                                         CHECKGLERROR
12765                                         qglBegin(GL_LINES);
12766                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12767                                         {
12768                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12769                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12770                                                 qglVertex3f(v[0], v[1], v[2]);
12771                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12772                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12773                                                 qglVertex3f(v[0], v[1], v[2]);
12774                                         }
12775                                         qglEnd();
12776                                         CHECKGLERROR
12777                                         qglBegin(GL_LINES);
12778                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12779                                         {
12780                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12781                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12782                                                 qglVertex3f(v[0], v[1], v[2]);
12783                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12784                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12785                                                 qglVertex3f(v[0], v[1], v[2]);
12786                                         }
12787                                         qglEnd();
12788                                         CHECKGLERROR
12789                                 }
12790                         }
12791                 }
12792                 rsurface.texture = NULL;
12793         }
12794 }
12795
12796 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12797 int r_maxsurfacelist = 0;
12798 const msurface_t **r_surfacelist = NULL;
12799 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12800 {
12801         int i, j, endj, flagsmask;
12802         dp_model_t *model = r_refdef.scene.worldmodel;
12803         msurface_t *surfaces;
12804         unsigned char *update;
12805         int numsurfacelist = 0;
12806         if (model == NULL)
12807                 return;
12808
12809         if (r_maxsurfacelist < model->num_surfaces)
12810         {
12811                 r_maxsurfacelist = model->num_surfaces;
12812                 if (r_surfacelist)
12813                         Mem_Free((msurface_t**)r_surfacelist);
12814                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12815         }
12816
12817         RSurf_ActiveWorldEntity();
12818
12819         surfaces = model->data_surfaces;
12820         update = model->brushq1.lightmapupdateflags;
12821
12822         // update light styles on this submodel
12823         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12824         {
12825                 model_brush_lightstyleinfo_t *style;
12826                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12827                 {
12828                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12829                         {
12830                                 int *list = style->surfacelist;
12831                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12832                                 for (j = 0;j < style->numsurfaces;j++)
12833                                         update[list[j]] = true;
12834                         }
12835                 }
12836         }
12837
12838         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12839
12840         if (debug)
12841         {
12842                 R_DrawDebugModel();
12843                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12844                 return;
12845         }
12846
12847         rsurface.lightmaptexture = NULL;
12848         rsurface.deluxemaptexture = NULL;
12849         rsurface.uselightmaptexture = false;
12850         rsurface.texture = NULL;
12851         rsurface.rtlight = NULL;
12852         numsurfacelist = 0;
12853         // add visible surfaces to draw list
12854         for (i = 0;i < model->nummodelsurfaces;i++)
12855         {
12856                 j = model->sortedmodelsurfaces[i];
12857                 if (r_refdef.viewcache.world_surfacevisible[j])
12858                         r_surfacelist[numsurfacelist++] = surfaces + j;
12859         }
12860         // update lightmaps if needed
12861         if (model->brushq1.firstrender)
12862         {
12863                 model->brushq1.firstrender = false;
12864                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12865                         if (update[j])
12866                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12867         }
12868         else if (update)
12869         {
12870                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12871                         if (r_refdef.viewcache.world_surfacevisible[j])
12872                                 if (update[j])
12873                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12874         }
12875         // don't do anything if there were no surfaces
12876         if (!numsurfacelist)
12877         {
12878                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12879                 return;
12880         }
12881         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12882         GL_AlphaTest(false);
12883
12884         // add to stats if desired
12885         if (r_speeds.integer && !skysurfaces && !depthonly)
12886         {
12887                 r_refdef.stats.world_surfaces += numsurfacelist;
12888                 for (j = 0;j < numsurfacelist;j++)
12889                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12890         }
12891
12892         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12893 }
12894
12895 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12896 {
12897         int i, j, endj, flagsmask;
12898         dp_model_t *model = ent->model;
12899         msurface_t *surfaces;
12900         unsigned char *update;
12901         int numsurfacelist = 0;
12902         if (model == NULL)
12903                 return;
12904
12905         if (r_maxsurfacelist < model->num_surfaces)
12906         {
12907                 r_maxsurfacelist = model->num_surfaces;
12908                 if (r_surfacelist)
12909                         Mem_Free((msurface_t **)r_surfacelist);
12910                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12911         }
12912
12913         // if the model is static it doesn't matter what value we give for
12914         // wantnormals and wanttangents, so this logic uses only rules applicable
12915         // to a model, knowing that they are meaningless otherwise
12916         if (ent == r_refdef.scene.worldentity)
12917                 RSurf_ActiveWorldEntity();
12918         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12919                 RSurf_ActiveModelEntity(ent, false, false, false);
12920         else if (prepass)
12921                 RSurf_ActiveModelEntity(ent, true, true, true);
12922         else if (depthonly)
12923         {
12924                 switch (vid.renderpath)
12925                 {
12926                 case RENDERPATH_GL20:
12927                 case RENDERPATH_CGGL:
12928                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12929                         break;
12930                 case RENDERPATH_GL13:
12931                 case RENDERPATH_GL11:
12932                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12933                         break;
12934                 }
12935         }
12936         else
12937         {
12938                 switch (vid.renderpath)
12939                 {
12940                 case RENDERPATH_GL20:
12941                 case RENDERPATH_CGGL:
12942                         RSurf_ActiveModelEntity(ent, true, true, false);
12943                         break;
12944                 case RENDERPATH_GL13:
12945                 case RENDERPATH_GL11:
12946                         RSurf_ActiveModelEntity(ent, true, false, false);
12947                         break;
12948                 }
12949         }
12950
12951         surfaces = model->data_surfaces;
12952         update = model->brushq1.lightmapupdateflags;
12953
12954         // update light styles
12955         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12956         {
12957                 model_brush_lightstyleinfo_t *style;
12958                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12959                 {
12960                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12961                         {
12962                                 int *list = style->surfacelist;
12963                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12964                                 for (j = 0;j < style->numsurfaces;j++)
12965                                         update[list[j]] = true;
12966                         }
12967                 }
12968         }
12969
12970         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12971
12972         if (debug)
12973         {
12974                 R_DrawDebugModel();
12975                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12976                 return;
12977         }
12978
12979         rsurface.lightmaptexture = NULL;
12980         rsurface.deluxemaptexture = NULL;
12981         rsurface.uselightmaptexture = false;
12982         rsurface.texture = NULL;
12983         rsurface.rtlight = NULL;
12984         numsurfacelist = 0;
12985         // add visible surfaces to draw list
12986         for (i = 0;i < model->nummodelsurfaces;i++)
12987                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12988         // don't do anything if there were no surfaces
12989         if (!numsurfacelist)
12990         {
12991                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12992                 return;
12993         }
12994         // update lightmaps if needed
12995         if (update)
12996         {
12997                 int updated = 0;
12998                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12999                 {
13000                         if (update[j])
13001                         {
13002                                 updated++;
13003                                 R_BuildLightMap(ent, surfaces + j);
13004                         }
13005                 }
13006         }
13007         if (update)
13008                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13009                         if (update[j])
13010                                 R_BuildLightMap(ent, surfaces + j);
13011         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13012         GL_AlphaTest(false);
13013
13014         // add to stats if desired
13015         if (r_speeds.integer && !skysurfaces && !depthonly)
13016         {
13017                 r_refdef.stats.entities_surfaces += numsurfacelist;
13018                 for (j = 0;j < numsurfacelist;j++)
13019                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13020         }
13021
13022         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13023 }
13024
13025 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13026 {
13027         static texture_t texture;
13028         static msurface_t surface;
13029         const msurface_t *surfacelist = &surface;
13030
13031         // fake enough texture and surface state to render this geometry
13032
13033         texture.update_lastrenderframe = -1; // regenerate this texture
13034         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13035         texture.currentskinframe = skinframe;
13036         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13037         texture.offsetmapping = OFFSETMAPPING_OFF;
13038         texture.offsetscale = 1;
13039         texture.specularscalemod = 1;
13040         texture.specularpowermod = 1;
13041
13042         surface.texture = &texture;
13043         surface.num_triangles = numtriangles;
13044         surface.num_firsttriangle = firsttriangle;
13045         surface.num_vertices = numvertices;
13046         surface.num_firstvertex = firstvertex;
13047
13048         // now render it
13049         rsurface.texture = R_GetCurrentTexture(surface.texture);
13050         rsurface.lightmaptexture = NULL;
13051         rsurface.deluxemaptexture = NULL;
13052         rsurface.uselightmaptexture = false;
13053         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13054 }
13055
13056 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)
13057 {
13058         static msurface_t surface;
13059         const msurface_t *surfacelist = &surface;
13060
13061         // fake enough texture and surface state to render this geometry
13062
13063         surface.texture = texture;
13064         surface.num_triangles = numtriangles;
13065         surface.num_firsttriangle = firsttriangle;
13066         surface.num_vertices = numvertices;
13067         surface.num_firstvertex = firstvertex;
13068
13069         // now render it
13070         rsurface.texture = R_GetCurrentTexture(surface.texture);
13071         rsurface.lightmaptexture = NULL;
13072         rsurface.deluxemaptexture = NULL;
13073         rsurface.uselightmaptexture = false;
13074         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13075 }