]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
a third console picture layer. NOW we should be able to do about anything remotely...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #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_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
80 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
81 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
82 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
83 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
84 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)"};
85 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)"};
86 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
87 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
88 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
89 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
90 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
91 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
92 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
93 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."};
94 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
95 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
96 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
97 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."};
98 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
99 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
100 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
101 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
102 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"};
103 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"};
104 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
105 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
106 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
107 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
108 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"};
109
110 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
111 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
112 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
113 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
114 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
115 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
116 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
117 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
118
119 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)"};
120 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"};
121
122 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
123 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
124 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
125 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
126 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
127
128 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
129 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
130 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
131
132 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)"};
133 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
134 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
135 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
136 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
137 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)"};
138 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)"};
139 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)"};
140 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)"};
141
142 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)"};
143 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
144 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"};
145 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
146 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
147
148 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
149 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
150 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
151 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
152
153 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
154 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
155 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
156 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
157 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
158 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
159 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
160
161 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
162 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
163 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
164 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)"};
165
166 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"};
167
168 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"};
169
170 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
171
172 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
173 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"};
174 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
175 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
176 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
177 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
178 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)"};
179
180 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
181
182 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)"};
183
184 extern cvar_t v_glslgamma;
185
186 extern qboolean v_flipped_state;
187
188 static struct r_bloomstate_s
189 {
190         qboolean enabled;
191         qboolean hdr;
192
193         int bloomwidth, bloomheight;
194
195         int screentexturewidth, screentextureheight;
196         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
197
198         int bloomtexturewidth, bloomtextureheight;
199         rtexture_t *texture_bloom;
200
201         // arrays for rendering the screen passes
202         float screentexcoord2f[8];
203         float bloomtexcoord2f[8];
204         float offsettexcoord2f[8];
205
206         r_viewport_t viewport;
207 }
208 r_bloomstate;
209
210 r_waterstate_t r_waterstate;
211
212 /// shadow volume bsp struct with automatically growing nodes buffer
213 svbsp_t r_svbsp;
214
215 rtexture_t *r_texture_blanknormalmap;
216 rtexture_t *r_texture_white;
217 rtexture_t *r_texture_grey128;
218 rtexture_t *r_texture_black;
219 rtexture_t *r_texture_notexture;
220 rtexture_t *r_texture_whitecube;
221 rtexture_t *r_texture_normalizationcube;
222 rtexture_t *r_texture_fogattenuation;
223 rtexture_t *r_texture_fogheighttexture;
224 rtexture_t *r_texture_gammaramps;
225 unsigned int r_texture_gammaramps_serial;
226 //rtexture_t *r_texture_fogintensity;
227 rtexture_t *r_texture_reflectcube;
228
229 // TODO: hash lookups?
230 typedef struct cubemapinfo_s
231 {
232         char basename[64];
233         rtexture_t *texture;
234 }
235 cubemapinfo_t;
236
237 int r_texture_numcubemaps;
238 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
239
240 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
241 unsigned int r_numqueries;
242 unsigned int r_maxqueries;
243
244 typedef struct r_qwskincache_s
245 {
246         char name[MAX_QPATH];
247         skinframe_t *skinframe;
248 }
249 r_qwskincache_t;
250
251 static r_qwskincache_t *r_qwskincache;
252 static int r_qwskincache_size;
253
254 /// vertex coordinates for a quad that covers the screen exactly
255 const float r_screenvertex3f[12] =
256 {
257         0, 0, 0,
258         1, 0, 0,
259         1, 1, 0,
260         0, 1, 0
261 };
262
263 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
264 {
265         int i;
266         for (i = 0;i < verts;i++)
267         {
268                 out[0] = in[0] * r;
269                 out[1] = in[1] * g;
270                 out[2] = in[2] * b;
271                 out[3] = in[3];
272                 in += 4;
273                 out += 4;
274         }
275 }
276
277 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = r;
283                 out[1] = g;
284                 out[2] = b;
285                 out[3] = a;
286                 out += 4;
287         }
288 }
289
290 // FIXME: move this to client?
291 void FOG_clear(void)
292 {
293         if (gamemode == GAME_NEHAHRA)
294         {
295                 Cvar_Set("gl_fogenable", "0");
296                 Cvar_Set("gl_fogdensity", "0.2");
297                 Cvar_Set("gl_fogred", "0.3");
298                 Cvar_Set("gl_foggreen", "0.3");
299                 Cvar_Set("gl_fogblue", "0.3");
300         }
301         r_refdef.fog_density = 0;
302         r_refdef.fog_red = 0;
303         r_refdef.fog_green = 0;
304         r_refdef.fog_blue = 0;
305         r_refdef.fog_alpha = 1;
306         r_refdef.fog_start = 0;
307         r_refdef.fog_end = 16384;
308         r_refdef.fog_height = 1<<30;
309         r_refdef.fog_fadedepth = 128;
310         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
311 }
312
313 static void R_BuildBlankTextures(void)
314 {
315         unsigned char data[4];
316         data[2] = 128; // normal X
317         data[1] = 128; // normal Y
318         data[0] = 255; // normal Z
319         data[3] = 128; // height
320         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
321         data[0] = 255;
322         data[1] = 255;
323         data[2] = 255;
324         data[3] = 255;
325         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
326         data[0] = 128;
327         data[1] = 128;
328         data[2] = 128;
329         data[3] = 255;
330         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
331         data[0] = 0;
332         data[1] = 0;
333         data[2] = 0;
334         data[3] = 255;
335         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
336 }
337
338 static void R_BuildNoTexture(void)
339 {
340         int x, y;
341         unsigned char pix[16][16][4];
342         // this makes a light grey/dark grey checkerboard texture
343         for (y = 0;y < 16;y++)
344         {
345                 for (x = 0;x < 16;x++)
346                 {
347                         if ((y < 8) ^ (x < 8))
348                         {
349                                 pix[y][x][0] = 128;
350                                 pix[y][x][1] = 128;
351                                 pix[y][x][2] = 128;
352                                 pix[y][x][3] = 255;
353                         }
354                         else
355                         {
356                                 pix[y][x][0] = 64;
357                                 pix[y][x][1] = 64;
358                                 pix[y][x][2] = 64;
359                                 pix[y][x][3] = 255;
360                         }
361                 }
362         }
363         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
364 }
365
366 static void R_BuildWhiteCube(void)
367 {
368         unsigned char data[6*1*1*4];
369         memset(data, 255, sizeof(data));
370         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildNormalizationCube(void)
374 {
375         int x, y, side;
376         vec3_t v;
377         vec_t s, t, intensity;
378 #define NORMSIZE 64
379         unsigned char *data;
380         data = Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
381         for (side = 0;side < 6;side++)
382         {
383                 for (y = 0;y < NORMSIZE;y++)
384                 {
385                         for (x = 0;x < NORMSIZE;x++)
386                         {
387                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
388                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
389                                 switch(side)
390                                 {
391                                 default:
392                                 case 0:
393                                         v[0] = 1;
394                                         v[1] = -t;
395                                         v[2] = -s;
396                                         break;
397                                 case 1:
398                                         v[0] = -1;
399                                         v[1] = -t;
400                                         v[2] = s;
401                                         break;
402                                 case 2:
403                                         v[0] = s;
404                                         v[1] = 1;
405                                         v[2] = t;
406                                         break;
407                                 case 3:
408                                         v[0] = s;
409                                         v[1] = -1;
410                                         v[2] = -t;
411                                         break;
412                                 case 4:
413                                         v[0] = s;
414                                         v[1] = -t;
415                                         v[2] = 1;
416                                         break;
417                                 case 5:
418                                         v[0] = -s;
419                                         v[1] = -t;
420                                         v[2] = -1;
421                                         break;
422                                 }
423                                 intensity = 127.0f / sqrt(DotProduct(v, v));
424                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
425                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
426                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
427                                 data[((side*64+y)*64+x)*4+3] = 255;
428                         }
429                 }
430         }
431         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432         Mem_Free(data);
433 }
434
435 static void R_BuildFogTexture(void)
436 {
437         int x, b;
438 #define FOGWIDTH 256
439         unsigned char data1[FOGWIDTH][4];
440         //unsigned char data2[FOGWIDTH][4];
441         double d, r, alpha;
442
443         r_refdef.fogmasktable_start = r_refdef.fog_start;
444         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
445         r_refdef.fogmasktable_range = r_refdef.fogrange;
446         r_refdef.fogmasktable_density = r_refdef.fog_density;
447
448         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
449         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
450         {
451                 d = (x * r - r_refdef.fogmasktable_start);
452                 if(developer_extra.integer)
453                         Con_DPrintf("%f ", d);
454                 d = max(0, d);
455                 if (r_fog_exp2.integer)
456                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
457                 else
458                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
459                 if(developer_extra.integer)
460                         Con_DPrintf(" : %f ", alpha);
461                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
462                 if(developer_extra.integer)
463                         Con_DPrintf(" = %f\n", alpha);
464                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
465         }
466
467         for (x = 0;x < FOGWIDTH;x++)
468         {
469                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
470                 data1[x][0] = b;
471                 data1[x][1] = b;
472                 data1[x][2] = b;
473                 data1[x][3] = 255;
474                 //data2[x][0] = 255 - b;
475                 //data2[x][1] = 255 - b;
476                 //data2[x][2] = 255 - b;
477                 //data2[x][3] = 255;
478         }
479         if (r_texture_fogattenuation)
480         {
481                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
482                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
483         }
484         else
485         {
486                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
487                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_ALLOWUPDATES, NULL);
488         }
489 }
490
491 static void R_BuildFogHeightTexture(void)
492 {
493         unsigned char *inpixels;
494         int size;
495         int x;
496         int y;
497         int j;
498         float c[4];
499         float f;
500         inpixels = NULL;
501         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
502         if (r_refdef.fogheighttexturename[0])
503                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
504         if (!inpixels)
505         {
506                 r_refdef.fog_height_tablesize = 0;
507                 if (r_texture_fogheighttexture)
508                         R_FreeTexture(r_texture_fogheighttexture);
509                 r_texture_fogheighttexture = NULL;
510                 if (r_refdef.fog_height_table2d)
511                         Mem_Free(r_refdef.fog_height_table2d);
512                 r_refdef.fog_height_table2d = NULL;
513                 if (r_refdef.fog_height_table1d)
514                         Mem_Free(r_refdef.fog_height_table1d);
515                 r_refdef.fog_height_table1d = NULL;
516                 return;
517         }
518         size = image_width;
519         r_refdef.fog_height_tablesize = size;
520         r_refdef.fog_height_table1d = Mem_Alloc(r_main_mempool, size * 4);
521         r_refdef.fog_height_table2d = Mem_Alloc(r_main_mempool, size * size * 4);
522         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
523         Mem_Free(inpixels);
524         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
525         // average fog color table accounting for every fog layer between a point
526         // and the camera.  (Note: attenuation is handled separately!)
527         for (y = 0;y < size;y++)
528         {
529                 for (x = 0;x < size;x++)
530                 {
531                         Vector4Clear(c);
532                         f = 0;
533                         if (x < y)
534                         {
535                                 for (j = x;j <= y;j++)
536                                 {
537                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
538                                         f++;
539                                 }
540                         }
541                         else
542                         {
543                                 for (j = x;j >= y;j--)
544                                 {
545                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
546                                         f++;
547                                 }
548                         }
549                         f = 1.0f / f;
550                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
551                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
552                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
553                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
554                 }
555         }
556         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
557 }
558
559 //=======================================================================================================================================================
560
561 static const char *builtinshaderstring =
562 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
563 "// written by Forest 'LordHavoc' Hale\n"
564 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
565 "\n"
566 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
567 "# define USEFOG\n"
568 "#endif\n"
569 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
570 "#define USELIGHTMAP\n"
571 "#endif\n"
572 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
573 "#define USEEYEVECTOR\n"
574 "#endif\n"
575 "\n"
576 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
577 "# extension GL_ARB_texture_rectangle : enable\n"
578 "#endif\n"
579 "\n"
580 "#ifdef USESHADOWMAP2D\n"
581 "# ifdef GL_EXT_gpu_shader4\n"
582 "#   extension GL_EXT_gpu_shader4 : enable\n"
583 "# endif\n"
584 "# ifdef GL_ARB_texture_gather\n"
585 "#   extension GL_ARB_texture_gather : enable\n"
586 "# else\n"
587 "#   ifdef GL_AMD_texture_texture4\n"
588 "#     extension GL_AMD_texture_texture4 : enable\n"
589 "#   endif\n"
590 "# endif\n"
591 "#endif\n"
592 "\n"
593 "#ifdef USESHADOWMAPCUBE\n"
594 "# extension GL_EXT_gpu_shader4 : enable\n"
595 "#endif\n"
596 "\n"
597 "//#ifdef USESHADOWSAMPLER\n"
598 "//# extension GL_ARB_shadow : enable\n"
599 "//#endif\n"
600 "\n"
601 "//#ifdef __GLSL_CG_DATA_TYPES\n"
602 "//# define myhalf half\n"
603 "//# define myhalf2 half2\n"
604 "//# define myhalf3 half3\n"
605 "//# define myhalf4 half4\n"
606 "//#else\n"
607 "# define myhalf float\n"
608 "# define myhalf2 vec2\n"
609 "# define myhalf3 vec3\n"
610 "# define myhalf4 vec4\n"
611 "//#endif\n"
612 "\n"
613 "#ifdef VERTEX_SHADER\n"
614 "uniform mat4 ModelViewProjectionMatrix;\n"
615 "#endif\n"
616 "\n"
617 "#ifdef MODE_DEPTH_OR_SHADOW\n"
618 "#ifdef VERTEX_SHADER\n"
619 "void main(void)\n"
620 "{\n"
621 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
622 "}\n"
623 "#endif\n"
624 "#else // !MODE_DEPTH_ORSHADOW\n"
625 "\n"
626 "\n"
627 "\n"
628 "\n"
629 "#ifdef MODE_SHOWDEPTH\n"
630 "#ifdef VERTEX_SHADER\n"
631 "void main(void)\n"
632 "{\n"
633 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
634 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
635 "}\n"
636 "#endif\n"
637 "\n"
638 "#ifdef FRAGMENT_SHADER\n"
639 "void main(void)\n"
640 "{\n"
641 "       gl_FragColor = gl_Color;\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_SHOWDEPTH\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_POSTPROCESS\n"
650 "varying vec2 TexCoord1;\n"
651 "varying vec2 TexCoord2;\n"
652 "\n"
653 "#ifdef VERTEX_SHADER\n"
654 "void main(void)\n"
655 "{\n"
656 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
657 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
658 "#ifdef USEBLOOM\n"
659 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
660 "#endif\n"
661 "}\n"
662 "#endif\n"
663 "\n"
664 "#ifdef FRAGMENT_SHADER\n"
665 "uniform sampler2D Texture_First;\n"
666 "#ifdef USEBLOOM\n"
667 "uniform sampler2D Texture_Second;\n"
668 "#endif\n"
669 "#ifdef USEGAMMARAMPS\n"
670 "uniform sampler2D Texture_GammaRamps;\n"
671 "#endif\n"
672 "#ifdef USESATURATION\n"
673 "uniform float Saturation;\n"
674 "#endif\n"
675 "#ifdef USEVIEWTINT\n"
676 "uniform vec4 ViewTintColor;\n"
677 "#endif\n"
678 "//uncomment these if you want to use them:\n"
679 "uniform vec4 UserVec1;\n"
680 "uniform vec4 UserVec2;\n"
681 "// uniform vec4 UserVec3;\n"
682 "// uniform vec4 UserVec4;\n"
683 "// uniform float ClientTime;\n"
684 "uniform vec2 PixelSize;\n"
685 "void main(void)\n"
686 "{\n"
687 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
688 "#ifdef USEBLOOM\n"
689 "       gl_FragColor += texture2D(Texture_Second, TexCoord2);\n"
690 "#endif\n"
691 "#ifdef USEVIEWTINT\n"
692 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
693 "#endif\n"
694 "\n"
695 "#ifdef USEPOSTPROCESSING\n"
696 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
697 "// 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"
698 "       float sobel = 1.0;\n"
699 "       // vec2 ts = textureSize(Texture_First, 0);\n"
700 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
701 "       vec2 px = PixelSize;\n"
702 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
703 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
704 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
705 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
706 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
707 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
708 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
709 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
710 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
711 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
712 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
713 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
714 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
715 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
716 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
717 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
718 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
719 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
720 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
721 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
722 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
723 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
724 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
725 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
726 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
727 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
728 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
729 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
730 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
731 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
732 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
733 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
734 "#endif\n"
735 "\n"
736 "#ifdef USESATURATION\n"
737 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
738 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
739 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
740 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USEGAMMARAMPS\n"
744 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
745 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
746 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
747 "#endif\n"
748 "}\n"
749 "#endif\n"
750 "#else // !MODE_POSTPROCESS\n"
751 "\n"
752 "\n"
753 "\n"
754 "\n"
755 "#ifdef MODE_GENERIC\n"
756 "#ifdef USEDIFFUSE\n"
757 "varying vec2 TexCoord1;\n"
758 "#endif\n"
759 "#ifdef USESPECULAR\n"
760 "varying vec2 TexCoord2;\n"
761 "#endif\n"
762 "#ifdef VERTEX_SHADER\n"
763 "void main(void)\n"
764 "{\n"
765 "       gl_FrontColor = gl_Color;\n"
766 "#ifdef USEDIFFUSE\n"
767 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
768 "#endif\n"
769 "#ifdef USESPECULAR\n"
770 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
771 "#endif\n"
772 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
773 "}\n"
774 "#endif\n"
775 "\n"
776 "#ifdef FRAGMENT_SHADER\n"
777 "#ifdef USEDIFFUSE\n"
778 "uniform sampler2D Texture_First;\n"
779 "#endif\n"
780 "#ifdef USESPECULAR\n"
781 "uniform sampler2D Texture_Second;\n"
782 "#endif\n"
783 "\n"
784 "void main(void)\n"
785 "{\n"
786 "       gl_FragColor = gl_Color;\n"
787 "#ifdef USEDIFFUSE\n"
788 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
789 "#endif\n"
790 "\n"
791 "#ifdef USESPECULAR\n"
792 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
793 "# ifdef USECOLORMAPPING\n"
794 "       gl_FragColor *= tex2;\n"
795 "# endif\n"
796 "# ifdef USEGLOW\n"
797 "       gl_FragColor += tex2;\n"
798 "# endif\n"
799 "# ifdef USEVERTEXTEXTUREBLEND\n"
800 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
801 "# endif\n"
802 "#endif\n"
803 "}\n"
804 "#endif\n"
805 "#else // !MODE_GENERIC\n"
806 "\n"
807 "\n"
808 "\n"
809 "\n"
810 "#ifdef MODE_BLOOMBLUR\n"
811 "varying TexCoord;\n"
812 "#ifdef VERTEX_SHADER\n"
813 "void main(void)\n"
814 "{\n"
815 "       gl_FrontColor = gl_Color;\n"
816 "       TexCoord = gl_MultiTexCoord0.xy;\n"
817 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
818 "}\n"
819 "#endif\n"
820 "\n"
821 "#ifdef FRAGMENT_SHADER\n"
822 "uniform sampler2D Texture_First;\n"
823 "uniform vec4 BloomBlur_Parameters;\n"
824 "\n"
825 "void main(void)\n"
826 "{\n"
827 "       int i;\n"
828 "       vec2 tc = TexCoord;\n"
829 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
830 "       tc += BloomBlur_Parameters.xy;\n"
831 "       for (i = 1;i < SAMPLES;i++)\n"
832 "       {\n"
833 "               color += texture2D(Texture_First, tc).rgb;\n"
834 "               tc += BloomBlur_Parameters.xy;\n"
835 "       }\n"
836 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
837 "}\n"
838 "#endif\n"
839 "#else // !MODE_BLOOMBLUR\n"
840 "#ifdef MODE_REFRACTION\n"
841 "varying vec2 TexCoord;\n"
842 "varying vec4 ModelViewProjectionPosition;\n"
843 "uniform mat4 TexMatrix;\n"
844 "#ifdef VERTEX_SHADER\n"
845 "\n"
846 "void main(void)\n"
847 "{\n"
848 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
849 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
850 "       ModelViewProjectionPosition = gl_Position;\n"
851 "}\n"
852 "#endif\n"
853 "\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_Normal;\n"
856 "uniform sampler2D Texture_Refraction;\n"
857 "uniform sampler2D Texture_Reflection;\n"
858 "\n"
859 "uniform vec4 DistortScaleRefractReflect;\n"
860 "uniform vec4 ScreenScaleRefractReflect;\n"
861 "uniform vec4 ScreenCenterRefractReflect;\n"
862 "uniform vec4 RefractColor;\n"
863 "uniform vec4 ReflectColor;\n"
864 "uniform float ReflectFactor;\n"
865 "uniform float ReflectOffset;\n"
866 "\n"
867 "void main(void)\n"
868 "{\n"
869 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
870 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
871 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
872 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
873 "       // FIXME temporary hack to detect the case that the reflection\n"
874 "       // gets blackened at edges due to leaving the area that contains actual\n"
875 "       // content.\n"
876 "       // Remove this 'ack once we have a better way to stop this thing from\n"
877 "       // 'appening.\n"
878 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
879 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
880 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
881 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
882 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
883 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
884 "}\n"
885 "#endif\n"
886 "#else // !MODE_REFRACTION\n"
887 "\n"
888 "\n"
889 "\n"
890 "\n"
891 "#ifdef MODE_WATER\n"
892 "varying vec2 TexCoord;\n"
893 "varying vec3 EyeVector;\n"
894 "varying vec4 ModelViewProjectionPosition;\n"
895 "#ifdef VERTEX_SHADER\n"
896 "uniform vec3 EyePosition;\n"
897 "uniform mat4 TexMatrix;\n"
898 "\n"
899 "void main(void)\n"
900 "{\n"
901 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
902 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
903 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
904 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
905 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
906 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
907 "       ModelViewProjectionPosition = gl_Position;\n"
908 "}\n"
909 "#endif\n"
910 "\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
915 "\n"
916 "uniform vec4 DistortScaleRefractReflect;\n"
917 "uniform vec4 ScreenScaleRefractReflect;\n"
918 "uniform vec4 ScreenCenterRefractReflect;\n"
919 "uniform vec4 RefractColor;\n"
920 "uniform vec4 ReflectColor;\n"
921 "uniform float ReflectFactor;\n"
922 "uniform float ReflectOffset;\n"
923 "\n"
924 "void main(void)\n"
925 "{\n"
926 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
927 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
928 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
929 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
930 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
931 "       // FIXME temporary hack to detect the case that the reflection\n"
932 "       // gets blackened at edges due to leaving the area that contains actual\n"
933 "       // content.\n"
934 "       // Remove this 'ack once we have a better way to stop this thing from\n"
935 "       // 'appening.\n"
936 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
937 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
939 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
940 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
941 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
942 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
943 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
945 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
946 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
947 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
948 "}\n"
949 "#endif\n"
950 "#else // !MODE_WATER\n"
951 "\n"
952 "\n"
953 "\n"
954 "\n"
955 "// common definitions between vertex shader and fragment shader:\n"
956 "\n"
957 "varying vec2 TexCoord;\n"
958 "#ifdef USEVERTEXTEXTUREBLEND\n"
959 "varying vec2 TexCoord2;\n"
960 "#endif\n"
961 "#ifdef USELIGHTMAP\n"
962 "varying vec2 TexCoordLightmap;\n"
963 "#endif\n"
964 "\n"
965 "#ifdef MODE_LIGHTSOURCE\n"
966 "varying vec3 CubeVector;\n"
967 "#endif\n"
968 "\n"
969 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
970 "varying vec3 LightVector;\n"
971 "#endif\n"
972 "\n"
973 "#ifdef USEEYEVECTOR\n"
974 "varying vec3 EyeVector;\n"
975 "#endif\n"
976 "#ifdef USEFOG\n"
977 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
978 "#endif\n"
979 "\n"
980 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
981 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
982 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
983 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
984 "#endif\n"
985 "\n"
986 "#ifdef USEREFLECTION\n"
987 "varying vec4 ModelViewProjectionPosition;\n"
988 "#endif\n"
989 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
990 "uniform vec3 LightPosition;\n"
991 "varying vec4 ModelViewPosition;\n"
992 "#endif\n"
993 "\n"
994 "#ifdef MODE_LIGHTSOURCE\n"
995 "uniform vec3 LightPosition;\n"
996 "#endif\n"
997 "uniform vec3 EyePosition;\n"
998 "#ifdef MODE_LIGHTDIRECTION\n"
999 "uniform vec3 LightDir;\n"
1000 "#endif\n"
1001 "uniform vec4 FogPlane;\n"
1002 "\n"
1003 "#ifdef USESHADOWMAPORTHO\n"
1004 "varying vec3 ShadowMapTC;\n"
1005 "#endif\n"
1006 "\n"
1007 "\n"
1008 "\n"
1009 "\n"
1010 "\n"
1011 "// 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"
1012 "\n"
1013 "// fragment shader specific:\n"
1014 "#ifdef FRAGMENT_SHADER\n"
1015 "\n"
1016 "uniform sampler2D Texture_Normal;\n"
1017 "uniform sampler2D Texture_Color;\n"
1018 "uniform sampler2D Texture_Gloss;\n"
1019 "#ifdef USEGLOW\n"
1020 "uniform sampler2D Texture_Glow;\n"
1021 "#endif\n"
1022 "#ifdef USEVERTEXTEXTUREBLEND\n"
1023 "uniform sampler2D Texture_SecondaryNormal;\n"
1024 "uniform sampler2D Texture_SecondaryColor;\n"
1025 "uniform sampler2D Texture_SecondaryGloss;\n"
1026 "#ifdef USEGLOW\n"
1027 "uniform sampler2D Texture_SecondaryGlow;\n"
1028 "#endif\n"
1029 "#endif\n"
1030 "#ifdef USECOLORMAPPING\n"
1031 "uniform sampler2D Texture_Pants;\n"
1032 "uniform sampler2D Texture_Shirt;\n"
1033 "#endif\n"
1034 "#ifdef USEFOG\n"
1035 "#ifdef USEFOGHEIGHTTEXTURE\n"
1036 "uniform sampler2D Texture_FogHeightTexture;\n"
1037 "#endif\n"
1038 "uniform sampler2D Texture_FogMask;\n"
1039 "#endif\n"
1040 "#ifdef USELIGHTMAP\n"
1041 "uniform sampler2D Texture_Lightmap;\n"
1042 "#endif\n"
1043 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1044 "uniform sampler2D Texture_Deluxemap;\n"
1045 "#endif\n"
1046 "#ifdef USEREFLECTION\n"
1047 "uniform sampler2D Texture_Reflection;\n"
1048 "#endif\n"
1049 "\n"
1050 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1051 "uniform sampler2D Texture_ScreenDepth;\n"
1052 "uniform sampler2D Texture_ScreenNormalMap;\n"
1053 "#endif\n"
1054 "#ifdef USEDEFERREDLIGHTMAP\n"
1055 "uniform sampler2D Texture_ScreenDiffuse;\n"
1056 "uniform sampler2D Texture_ScreenSpecular;\n"
1057 "#endif\n"
1058 "\n"
1059 "uniform myhalf3 Color_Pants;\n"
1060 "uniform myhalf3 Color_Shirt;\n"
1061 "uniform myhalf3 FogColor;\n"
1062 "\n"
1063 "#ifdef USEFOG\n"
1064 "uniform float FogRangeRecip;\n"
1065 "uniform float FogPlaneViewDist;\n"
1066 "uniform float FogHeightFade;\n"
1067 "vec3 FogVertex(vec3 surfacecolor)\n"
1068 "{\n"
1069 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1070 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1071 "       float fogfrac;\n"
1072 "#ifdef USEFOGHEIGHTTEXTURE\n"
1073 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1074 "       fogfrac = fogheightpixel.a;\n"
1075 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1076 "#else\n"
1077 "# ifdef USEFOGOUTSIDE\n"
1078 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1079 "# else\n"
1080 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1081 "# endif\n"
1082 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1083 "#endif\n"
1084 "}\n"
1085 "#endif\n"
1086 "\n"
1087 "#ifdef USEOFFSETMAPPING\n"
1088 "uniform float OffsetMapping_Scale;\n"
1089 "vec2 OffsetMapping(vec2 TexCoord)\n"
1090 "{\n"
1091 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1092 "       // 14 sample relief mapping: linear search and then binary search\n"
1093 "       // this basically steps forward a small amount repeatedly until it finds\n"
1094 "       // itself inside solid, then jitters forward and back using decreasing\n"
1095 "       // amounts to find the impact\n"
1096 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1097 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1098 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1099 "       vec3 RT = vec3(TexCoord, 1);\n"
1100 "       OffsetVector *= 0.1;\n"
1101 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1102 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1103 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1104 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1105 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1106 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1107 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1111 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1112 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1113 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1114 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1115 "       return RT.xy;\n"
1116 "#else\n"
1117 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1118 "       // this basically moves forward the full distance, and then backs up based\n"
1119 "       // on height of samples\n"
1120 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1121 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1122 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1123 "       TexCoord += OffsetVector;\n"
1124 "       OffsetVector *= 0.333;\n"
1125 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1126 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1127 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1128 "       return TexCoord;\n"
1129 "#endif\n"
1130 "}\n"
1131 "#endif // USEOFFSETMAPPING\n"
1132 "\n"
1133 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1134 "uniform sampler2D Texture_Attenuation;\n"
1135 "uniform samplerCube Texture_Cube;\n"
1136 "#endif\n"
1137 "\n"
1138 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1139 "\n"
1140 "#ifdef USESHADOWMAPRECT\n"
1141 "# ifdef USESHADOWSAMPLER\n"
1142 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1143 "# else\n"
1144 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1145 "# endif\n"
1146 "#endif\n"
1147 "\n"
1148 "#ifdef USESHADOWMAP2D\n"
1149 "# ifdef USESHADOWSAMPLER\n"
1150 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1151 "# else\n"
1152 "uniform sampler2D Texture_ShadowMap2D;\n"
1153 "# endif\n"
1154 "#endif\n"
1155 "\n"
1156 "#ifdef USESHADOWMAPVSDCT\n"
1157 "uniform samplerCube Texture_CubeProjection;\n"
1158 "#endif\n"
1159 "\n"
1160 "#ifdef USESHADOWMAPCUBE\n"
1161 "# ifdef USESHADOWSAMPLER\n"
1162 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1163 "# else\n"
1164 "uniform samplerCube Texture_ShadowMapCube;\n"
1165 "# endif\n"
1166 "#endif\n"
1167 "\n"
1168 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1169 "uniform vec2 ShadowMap_TextureScale;\n"
1170 "uniform vec4 ShadowMap_Parameters;\n"
1171 "#endif\n"
1172 "\n"
1173 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1174 "# ifdef USESHADOWMAPORTHO\n"
1175 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1176 "# else\n"
1177 "#  ifdef USESHADOWMAPVSDCT\n"
1178 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1179 "{\n"
1180 "       vec3 adir = abs(dir);\n"
1181 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1182 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1183 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1184 "}\n"
1185 "#  else\n"
1186 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1187 "{\n"
1188 "       vec3 adir = abs(dir);\n"
1189 "       float ma = adir.z;\n"
1190 "       vec4 proj = vec4(dir, 2.5);\n"
1191 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1192 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1193 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1194 "       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"
1195 "}\n"
1196 "#  endif\n"
1197 "# endif\n"
1198 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1199 "\n"
1200 "#ifdef USESHADOWMAPCUBE\n"
1201 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1205 "}\n"
1206 "#endif\n"
1207 "\n"
1208 "# ifdef USESHADOWMAPRECT\n"
1209 "float ShadowMapCompare(vec3 dir)\n"
1210 "{\n"
1211 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1212 "       float f;\n"
1213 "#  ifdef USESHADOWSAMPLER\n"
1214 "\n"
1215 "#    ifdef USESHADOWMAPPCF\n"
1216 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1217 "       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"
1218 "#    else\n"
1219 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1220 "#    endif\n"
1221 "\n"
1222 "#  else\n"
1223 "\n"
1224 "#    ifdef USESHADOWMAPPCF\n"
1225 "#      if USESHADOWMAPPCF > 1\n"
1226 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1227 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1228 "       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"
1229 "       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"
1230 "       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"
1231 "       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"
1232 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1233 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1234 "#      else\n"
1235 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1236 "       vec2 offset = fract(shadowmaptc.xy);\n"
1237 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1238 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1239 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1240 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1241 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1242 "#      endif\n"
1243 "#    else\n"
1244 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1245 "#    endif\n"
1246 "\n"
1247 "#  endif\n"
1248 "#  ifdef USESHADOWMAPORTHO\n"
1249 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1250 "#  else\n"
1251 "       return f;\n"
1252 "#  endif\n"
1253 "}\n"
1254 "# endif\n"
1255 "\n"
1256 "# ifdef USESHADOWMAP2D\n"
1257 "float ShadowMapCompare(vec3 dir)\n"
1258 "{\n"
1259 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1260 "       float f;\n"
1261 "\n"
1262 "#  ifdef USESHADOWSAMPLER\n"
1263 "#    ifdef USESHADOWMAPPCF\n"
1264 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1265 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1266 "       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"
1267 "#    else\n"
1268 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1269 "#    endif\n"
1270 "#  else\n"
1271 "#    ifdef USESHADOWMAPPCF\n"
1272 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1273 "#      ifdef GL_ARB_texture_gather\n"
1274 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1275 "#      else\n"
1276 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1277 "#      endif\n"
1278 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1279 "#      if USESHADOWMAPPCF > 1\n"
1280 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1281 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1282 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1283 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1284 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1285 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1286 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1287 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1288 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1289 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1290 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1291 "       locols.yz += group2.ab;\n"
1292 "       hicols.yz += group8.rg;\n"
1293 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1294 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1295 "                               mix(locols, hicols, offset.y);\n"
1296 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1297 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1298 "       f = dot(cols, vec4(1.0/25.0));\n"
1299 "#      else\n"
1300 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1301 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1302 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1303 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1304 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1305 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1306 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1307 "#      endif\n"
1308 "#     else\n"
1309 "#      ifdef GL_EXT_gpu_shader4\n"
1310 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1311 "#      else\n"
1312 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1313 "#      endif\n"
1314 "#      if USESHADOWMAPPCF > 1\n"
1315 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1316 "       center *= ShadowMap_TextureScale;\n"
1317 "       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"
1318 "       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"
1319 "       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"
1320 "       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"
1321 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1322 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1323 "#      else\n"
1324 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1325 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1326 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1327 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1328 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1329 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1330 "#      endif\n"
1331 "#     endif\n"
1332 "#    else\n"
1333 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1334 "#    endif\n"
1335 "#  endif\n"
1336 "#  ifdef USESHADOWMAPORTHO\n"
1337 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1338 "#  else\n"
1339 "       return f;\n"
1340 "#  endif\n"
1341 "}\n"
1342 "# endif\n"
1343 "\n"
1344 "# ifdef USESHADOWMAPCUBE\n"
1345 "float ShadowMapCompare(vec3 dir)\n"
1346 "{\n"
1347 "       // apply depth texture cubemap as light filter\n"
1348 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1349 "       float f;\n"
1350 "#  ifdef USESHADOWSAMPLER\n"
1351 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1352 "#  else\n"
1353 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1354 "#  endif\n"
1355 "       return f;\n"
1356 "}\n"
1357 "# endif\n"
1358 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1359 "#endif // FRAGMENT_SHADER\n"
1360 "\n"
1361 "\n"
1362 "\n"
1363 "\n"
1364 "#ifdef MODE_DEFERREDGEOMETRY\n"
1365 "#ifdef VERTEX_SHADER\n"
1366 "uniform mat4 TexMatrix;\n"
1367 "#ifdef USEVERTEXTEXTUREBLEND\n"
1368 "uniform mat4 BackgroundTexMatrix;\n"
1369 "#endif\n"
1370 "uniform mat4 ModelViewMatrix;\n"
1371 "void main(void)\n"
1372 "{\n"
1373 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1374 "#ifdef USEVERTEXTEXTUREBLEND\n"
1375 "       gl_FrontColor = gl_Color;\n"
1376 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1377 "#endif\n"
1378 "\n"
1379 "       // transform unnormalized eye direction into tangent space\n"
1380 "#ifdef USEOFFSETMAPPING\n"
1381 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1382 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1383 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1384 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1385 "#endif\n"
1386 "\n"
1387 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1388 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1389 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1390 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1391 "}\n"
1392 "#endif // VERTEX_SHADER\n"
1393 "\n"
1394 "#ifdef FRAGMENT_SHADER\n"
1395 "void main(void)\n"
1396 "{\n"
1397 "#ifdef USEOFFSETMAPPING\n"
1398 "       // apply offsetmapping\n"
1399 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1400 "#define TexCoord TexCoordOffset\n"
1401 "#endif\n"
1402 "\n"
1403 "#ifdef USEALPHAKILL\n"
1404 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1405 "               discard;\n"
1406 "#endif\n"
1407 "\n"
1408 "#ifdef USEVERTEXTEXTUREBLEND\n"
1409 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1410 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1411 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1412 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1413 "#endif\n"
1414 "\n"
1415 "#ifdef USEVERTEXTEXTUREBLEND\n"
1416 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1417 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1418 "#else\n"
1419 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1420 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1421 "#endif\n"
1422 "\n"
1423 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1424 "}\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDGEOMETRY\n"
1427 "\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1432 "#ifdef VERTEX_SHADER\n"
1433 "uniform mat4 ModelViewMatrix;\n"
1434 "void main(void)\n"
1435 "{\n"
1436 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1437 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1438 "}\n"
1439 "#endif // VERTEX_SHADER\n"
1440 "\n"
1441 "#ifdef FRAGMENT_SHADER\n"
1442 "uniform mat4 ViewToLight;\n"
1443 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1444 "uniform vec2 ScreenToDepth;\n"
1445 "uniform myhalf3 DeferredColor_Ambient;\n"
1446 "uniform myhalf3 DeferredColor_Diffuse;\n"
1447 "#ifdef USESPECULAR\n"
1448 "uniform myhalf3 DeferredColor_Specular;\n"
1449 "uniform myhalf SpecularPower;\n"
1450 "#endif\n"
1451 "uniform myhalf2 PixelToScreenTexCoord;\n"
1452 "void main(void)\n"
1453 "{\n"
1454 "       // calculate viewspace pixel position\n"
1455 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1456 "       vec3 position;\n"
1457 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1458 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1459 "       // decode viewspace pixel normal\n"
1460 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1461 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1462 "       // surfacenormal = pixel normal in viewspace\n"
1463 "       // LightVector = pixel to light in viewspace\n"
1464 "       // CubeVector = position in lightspace\n"
1465 "       // eyevector = pixel to view in viewspace\n"
1466 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1467 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1468 "#ifdef USEDIFFUSE\n"
1469 "       // calculate diffuse shading\n"
1470 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1471 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1472 "#endif\n"
1473 "#ifdef USESPECULAR\n"
1474 "       // calculate directional shading\n"
1475 "       vec3 eyevector = position * -1.0;\n"
1476 "#  ifdef USEEXACTSPECULARMATH\n"
1477 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1478 "#  else\n"
1479 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1480 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1481 "#  endif\n"
1482 "#endif\n"
1483 "\n"
1484 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1485 "       fade *= ShadowMapCompare(CubeVector);\n"
1486 "#endif\n"
1487 "\n"
1488 "#ifdef USEDIFFUSE\n"
1489 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1490 "#else\n"
1491 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1492 "#endif\n"
1493 "#ifdef USESPECULAR\n"
1494 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1495 "#else\n"
1496 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1497 "#endif\n"
1498 "\n"
1499 "# ifdef USECUBEFILTER\n"
1500 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1501 "       gl_FragData[0].rgb *= cubecolor;\n"
1502 "       gl_FragData[1].rgb *= cubecolor;\n"
1503 "# endif\n"
1504 "}\n"
1505 "#endif // FRAGMENT_SHADER\n"
1506 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1507 "\n"
1508 "\n"
1509 "\n"
1510 "\n"
1511 "#ifdef VERTEX_SHADER\n"
1512 "uniform mat4 TexMatrix;\n"
1513 "#ifdef USEVERTEXTEXTUREBLEND\n"
1514 "uniform mat4 BackgroundTexMatrix;\n"
1515 "#endif\n"
1516 "#ifdef MODE_LIGHTSOURCE\n"
1517 "uniform mat4 ModelToLight;\n"
1518 "#endif\n"
1519 "#ifdef USESHADOWMAPORTHO\n"
1520 "uniform mat4 ShadowMapMatrix;\n"
1521 "#endif\n"
1522 "void main(void)\n"
1523 "{\n"
1524 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1525 "       gl_FrontColor = gl_Color;\n"
1526 "#endif\n"
1527 "       // copy the surface texcoord\n"
1528 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1529 "#ifdef USEVERTEXTEXTUREBLEND\n"
1530 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1531 "#endif\n"
1532 "#ifdef USELIGHTMAP\n"
1533 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1534 "#endif\n"
1535 "\n"
1536 "#ifdef MODE_LIGHTSOURCE\n"
1537 "       // transform vertex position into light attenuation/cubemap space\n"
1538 "       // (-1 to +1 across the light box)\n"
1539 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1540 "\n"
1541 "# ifdef USEDIFFUSE\n"
1542 "       // transform unnormalized light direction into tangent space\n"
1543 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1544 "       //  normalize it per pixel)\n"
1545 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1546 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1547 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1548 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1549 "# endif\n"
1550 "#endif\n"
1551 "\n"
1552 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1553 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1554 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1555 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1556 "#endif\n"
1557 "\n"
1558 "       // transform unnormalized eye direction into tangent space\n"
1559 "#ifdef USEEYEVECTOR\n"
1560 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1561 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1562 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1563 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1564 "#endif\n"
1565 "\n"
1566 "#ifdef USEFOG\n"
1567 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1568 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1569 "#endif\n"
1570 "\n"
1571 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1572 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1573 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1574 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1575 "#endif\n"
1576 "\n"
1577 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1578 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1579 "\n"
1580 "#ifdef USESHADOWMAPORTHO\n"
1581 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1582 "#endif\n"
1583 "\n"
1584 "#ifdef USEREFLECTION\n"
1585 "       ModelViewProjectionPosition = gl_Position;\n"
1586 "#endif\n"
1587 "}\n"
1588 "#endif // VERTEX_SHADER\n"
1589 "\n"
1590 "\n"
1591 "\n"
1592 "\n"
1593 "#ifdef FRAGMENT_SHADER\n"
1594 "#ifdef USEDEFERREDLIGHTMAP\n"
1595 "uniform myhalf2 PixelToScreenTexCoord;\n"
1596 "uniform myhalf3 DeferredMod_Diffuse;\n"
1597 "uniform myhalf3 DeferredMod_Specular;\n"
1598 "#endif\n"
1599 "uniform myhalf3 Color_Ambient;\n"
1600 "uniform myhalf3 Color_Diffuse;\n"
1601 "uniform myhalf3 Color_Specular;\n"
1602 "uniform myhalf SpecularPower;\n"
1603 "#ifdef USEGLOW\n"
1604 "uniform myhalf3 Color_Glow;\n"
1605 "#endif\n"
1606 "uniform myhalf Alpha;\n"
1607 "#ifdef USEREFLECTION\n"
1608 "uniform vec4 DistortScaleRefractReflect;\n"
1609 "uniform vec4 ScreenScaleRefractReflect;\n"
1610 "uniform vec4 ScreenCenterRefractReflect;\n"
1611 "uniform myhalf4 ReflectColor;\n"
1612 "#endif\n"
1613 "#ifdef USEREFLECTCUBE\n"
1614 "uniform mat4 ModelToReflectCube;\n"
1615 "uniform sampler2D Texture_ReflectMask;\n"
1616 "uniform samplerCube Texture_ReflectCube;\n"
1617 "#endif\n"
1618 "#ifdef MODE_LIGHTDIRECTION\n"
1619 "uniform myhalf3 LightColor;\n"
1620 "#endif\n"
1621 "#ifdef MODE_LIGHTSOURCE\n"
1622 "uniform myhalf3 LightColor;\n"
1623 "#endif\n"
1624 "void main(void)\n"
1625 "{\n"
1626 "#ifdef USEOFFSETMAPPING\n"
1627 "       // apply offsetmapping\n"
1628 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1629 "#define TexCoord TexCoordOffset\n"
1630 "#endif\n"
1631 "\n"
1632 "       // combine the diffuse textures (base, pants, shirt)\n"
1633 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1634 "#ifdef USEALPHAKILL\n"
1635 "       if (color.a < 0.5)\n"
1636 "               discard;\n"
1637 "#endif\n"
1638 "       color.a *= Alpha;\n"
1639 "#ifdef USECOLORMAPPING\n"
1640 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1641 "#endif\n"
1642 "#ifdef USEVERTEXTEXTUREBLEND\n"
1643 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1644 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1645 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1646 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1647 "       color.a = 1.0;\n"
1648 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1649 "#endif\n"
1650 "\n"
1651 "       // get the surface normal\n"
1652 "#ifdef USEVERTEXTEXTUREBLEND\n"
1653 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1654 "#else\n"
1655 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1656 "#endif\n"
1657 "\n"
1658 "       // get the material colors\n"
1659 "       myhalf3 diffusetex = color.rgb;\n"
1660 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1661 "# ifdef USEVERTEXTEXTUREBLEND\n"
1662 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1663 "# else\n"
1664 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1665 "# endif\n"
1666 "#endif\n"
1667 "\n"
1668 "#ifdef USEREFLECTCUBE\n"
1669 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1670 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1671 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1672 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1673 "#endif\n"
1674 "\n"
1675 "\n"
1676 "\n"
1677 "\n"
1678 "#ifdef MODE_LIGHTSOURCE\n"
1679 "       // light source\n"
1680 "#ifdef USEDIFFUSE\n"
1681 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1682 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1684 "#ifdef USESPECULAR\n"
1685 "#ifdef USEEXACTSPECULARMATH\n"
1686 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1687 "#else\n"
1688 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1689 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1690 "#endif\n"
1691 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1692 "#endif\n"
1693 "#else\n"
1694 "       color.rgb = diffusetex * Color_Ambient;\n"
1695 "#endif\n"
1696 "       color.rgb *= LightColor;\n"
1697 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1698 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1699 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1700 "#endif\n"
1701 "# ifdef USECUBEFILTER\n"
1702 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1703 "# endif\n"
1704 "#endif // MODE_LIGHTSOURCE\n"
1705 "\n"
1706 "\n"
1707 "\n"
1708 "\n"
1709 "#ifdef MODE_LIGHTDIRECTION\n"
1710 "#define SHADING\n"
1711 "#ifdef USEDIFFUSE\n"
1712 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1713 "#endif\n"
1714 "#define lightcolor LightColor\n"
1715 "#endif // MODE_LIGHTDIRECTION\n"
1716 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1717 "#define SHADING\n"
1718 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1719 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1720 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1721 "       // convert modelspace light vector to tangentspace\n"
1722 "       myhalf3 lightnormal;\n"
1723 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1724 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1725 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1726 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1727 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1728 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1729 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1730 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1731 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1732 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1733 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1734 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1735 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1736 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1737 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1738 "#define SHADING\n"
1739 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1740 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1741 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1742 "#endif\n"
1743 "\n"
1744 "\n"
1745 "\n"
1746 "\n"
1747 "#ifdef MODE_LIGHTMAP\n"
1748 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1749 "#endif // MODE_LIGHTMAP\n"
1750 "#ifdef MODE_VERTEXCOLOR\n"
1751 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1752 "#endif // MODE_VERTEXCOLOR\n"
1753 "#ifdef MODE_FLATCOLOR\n"
1754 "       color.rgb = diffusetex * Color_Ambient;\n"
1755 "#endif // MODE_FLATCOLOR\n"
1756 "\n"
1757 "\n"
1758 "\n"
1759 "\n"
1760 "#ifdef SHADING\n"
1761 "# ifdef USEDIFFUSE\n"
1762 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1763 "#  ifdef USESPECULAR\n"
1764 "#   ifdef USEEXACTSPECULARMATH\n"
1765 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1766 "#   else\n"
1767 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1768 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1769 "#   endif\n"
1770 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1771 "#  else\n"
1772 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1773 "#  endif\n"
1774 "# else\n"
1775 "       color.rgb = diffusetex * Color_Ambient;\n"
1776 "# endif\n"
1777 "#endif\n"
1778 "\n"
1779 "#ifdef USESHADOWMAPORTHO\n"
1780 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1781 "#endif\n"
1782 "\n"
1783 "#ifdef USEDEFERREDLIGHTMAP\n"
1784 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1785 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1786 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1787 "#endif\n"
1788 "\n"
1789 "#ifdef USEGLOW\n"
1790 "#ifdef USEVERTEXTEXTUREBLEND\n"
1791 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1792 "#else\n"
1793 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1794 "#endif\n"
1795 "#endif\n"
1796 "\n"
1797 "#ifdef USEFOG\n"
1798 "       color.rgb = FogVertex(color.rgb);\n"
1799 "#endif\n"
1800 "\n"
1801 "       // 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"
1802 "#ifdef USEREFLECTION\n"
1803 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1804 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1805 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1806 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1807 "       // FIXME temporary hack to detect the case that the reflection\n"
1808 "       // gets blackened at edges due to leaving the area that contains actual\n"
1809 "       // content.\n"
1810 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1811 "       // 'appening.\n"
1812 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1813 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1814 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1815 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1816 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1817 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1818 "#endif\n"
1819 "\n"
1820 "       gl_FragColor = vec4(color);\n"
1821 "}\n"
1822 "#endif // FRAGMENT_SHADER\n"
1823 "\n"
1824 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1825 "#endif // !MODE_DEFERREDGEOMETRY\n"
1826 "#endif // !MODE_WATER\n"
1827 "#endif // !MODE_REFRACTION\n"
1828 "#endif // !MODE_BLOOMBLUR\n"
1829 "#endif // !MODE_GENERIC\n"
1830 "#endif // !MODE_POSTPROCESS\n"
1831 "#endif // !MODE_SHOWDEPTH\n"
1832 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1833 ;
1834
1835 /*
1836 =========================================================================================================================================================
1837
1838
1839
1840 =========================================================================================================================================================
1841
1842
1843
1844 =========================================================================================================================================================
1845
1846
1847
1848 =========================================================================================================================================================
1849
1850
1851
1852 =========================================================================================================================================================
1853
1854
1855
1856 =========================================================================================================================================================
1857
1858
1859
1860 =========================================================================================================================================================
1861 */
1862
1863 const char *builtincgshaderstring =
1864 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1865 "// written by Forest 'LordHavoc' Hale\n"
1866 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1867 "\n"
1868 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1869 "#if defined(USEREFLECTION)\n"
1870 "#undef USESHADOWMAPORTHO\n"
1871 "#endif\n"
1872 "\n"
1873 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1874 "# define USEFOG\n"
1875 "#endif\n"
1876 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1877 "#define USELIGHTMAP\n"
1878 "#endif\n"
1879 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1880 "#define USEEYEVECTOR\n"
1881 "#endif\n"
1882 "\n"
1883 "#ifdef FRAGMENT_SHADER\n"
1884 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1885 "#endif\n"
1886 "\n"
1887 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1888 "#ifdef VERTEX_SHADER\n"
1889 "void main\n"
1890 "(\n"
1891 "float4 gl_Vertex : POSITION,\n"
1892 "uniform float4x4 ModelViewProjectionMatrix,\n"
1893 "out float4 gl_Position : POSITION\n"
1894 ")\n"
1895 "{\n"
1896 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1897 "}\n"
1898 "#endif\n"
1899 "#else // !MODE_DEPTH_ORSHADOW\n"
1900 "\n"
1901 "\n"
1902 "\n"
1903 "\n"
1904 "#ifdef MODE_SHOWDEPTH\n"
1905 "#ifdef VERTEX_SHADER\n"
1906 "void main\n"
1907 "(\n"
1908 "float4 gl_Vertex : POSITION,\n"
1909 "uniform float4x4 ModelViewProjectionMatrix,\n"
1910 "out float4 gl_Position : POSITION,\n"
1911 "out float4 gl_FrontColor : COLOR0\n"
1912 ")\n"
1913 "{\n"
1914 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1915 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1916 "}\n"
1917 "#endif\n"
1918 "\n"
1919 "#ifdef FRAGMENT_SHADER\n"
1920 "void main\n"
1921 "(\n"
1922 "float4 gl_FrontColor : COLOR0,\n"
1923 "out float4 gl_FragColor : COLOR\n"
1924 ")\n"
1925 "{\n"
1926 "       gl_FragColor = gl_FrontColor;\n"
1927 "}\n"
1928 "#endif\n"
1929 "#else // !MODE_SHOWDEPTH\n"
1930 "\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "#ifdef MODE_POSTPROCESS\n"
1935 "\n"
1936 "#ifdef VERTEX_SHADER\n"
1937 "void main\n"
1938 "(\n"
1939 "float4 gl_Vertex : POSITION,\n"
1940 "uniform float4x4 ModelViewProjectionMatrix,\n"
1941 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1942 "float4 gl_MultiTexCoord1 : TEXCOORD4,\n"
1943 "out float4 gl_Position : POSITION,\n"
1944 "out float2 TexCoord1 : TEXCOORD0,\n"
1945 "out float2 TexCoord2 : TEXCOORD1\n"
1946 ")\n"
1947 "{\n"
1948 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1949 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1950 "#ifdef USEBLOOM\n"
1951 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
1952 "#endif\n"
1953 "}\n"
1954 "#endif\n"
1955 "\n"
1956 "#ifdef FRAGMENT_SHADER\n"
1957 "void main\n"
1958 "(\n"
1959 "float2 TexCoord1 : TEXCOORD0,\n"
1960 "float2 TexCoord2 : TEXCOORD1,\n"
1961 "uniform sampler2D Texture_First,\n"
1962 "#ifdef USEBLOOM\n"
1963 "uniform sampler2D Texture_Second,\n"
1964 "#endif\n"
1965 "#ifdef USEGAMMARAMPS\n"
1966 "uniform sampler2D Texture_GammaRamps,\n"
1967 "#endif\n"
1968 "#ifdef USESATURATION\n"
1969 "uniform float Saturation,\n"
1970 "#endif\n"
1971 "#ifdef USEVIEWTINT\n"
1972 "uniform float4 ViewTintColor,\n"
1973 "#endif\n"
1974 "uniform float4 UserVec1,\n"
1975 "uniform float4 UserVec2,\n"
1976 "uniform float4 UserVec3,\n"
1977 "uniform float4 UserVec4,\n"
1978 "uniform float ClientTime,\n"
1979 "uniform float2 PixelSize,\n"
1980 "out float4 gl_FragColor : COLOR\n"
1981 ")\n"
1982 "{\n"
1983 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1984 "#ifdef USEBLOOM\n"
1985 "       gl_FragColor += tex2D(Texture_Second, TexCoord2);\n"
1986 "#endif\n"
1987 "#ifdef USEVIEWTINT\n"
1988 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1989 "#endif\n"
1990 "\n"
1991 "#ifdef USEPOSTPROCESSING\n"
1992 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1993 "// 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"
1994 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1995 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1996 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1997 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1998 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1999 "       gl_FragColor /= (1 + 5 * UserVec1.y);\n"
2000 "#endif\n"
2001 "\n"
2002 "#ifdef USESATURATION\n"
2003 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2004 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2005 "       //gl_FragColor = float3(y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2006 "       gl_FragColor.rgb = lerp(float3(y), gl_FragColor.rgb, Saturation);\n"
2007 "#endif\n"
2008 "\n"
2009 "#ifdef USEGAMMARAMPS\n"
2010 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2011 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2012 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2013 "#endif\n"
2014 "}\n"
2015 "#endif\n"
2016 "#else // !MODE_POSTPROCESS\n"
2017 "\n"
2018 "\n"
2019 "\n"
2020 "\n"
2021 "#ifdef MODE_GENERIC\n"
2022 "#ifdef VERTEX_SHADER\n"
2023 "void main\n"
2024 "(\n"
2025 "float4 gl_Vertex : POSITION,\n"
2026 "uniform float4x4 ModelViewProjectionMatrix,\n"
2027 "float4 gl_Color : COLOR0,\n"
2028 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2029 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2030 "out float4 gl_Position : POSITION,\n"
2031 "out float4 gl_FrontColor : COLOR,\n"
2032 "out float2 TexCoord1 : TEXCOORD0,\n"
2033 "out float2 TexCoord2 : TEXCOORD1\n"
2034 ")\n"
2035 "{\n"
2036 "       gl_FrontColor = gl_Color;\n"
2037 "#ifdef USEDIFFUSE\n"
2038 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2039 "#endif\n"
2040 "#ifdef USESPECULAR\n"
2041 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2042 "#endif\n"
2043 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2044 "}\n"
2045 "#endif\n"
2046 "\n"
2047 "#ifdef FRAGMENT_SHADER\n"
2048 "\n"
2049 "void main\n"
2050 "(\n"
2051 "float4 gl_FrontColor : COLOR,\n"
2052 "float2 TexCoord1 : TEXCOORD0,\n"
2053 "float2 TexCoord2 : TEXCOORD1,\n"
2054 "#ifdef USEDIFFUSE\n"
2055 "uniform sampler2D Texture_First,\n"
2056 "#endif\n"
2057 "#ifdef USESPECULAR\n"
2058 "uniform sampler2D Texture_Second,\n"
2059 "#endif\n"
2060 "out float4 gl_FragColor : COLOR\n"
2061 ")\n"
2062 "{\n"
2063 "       gl_FragColor = gl_FrontColor;\n"
2064 "#ifdef USEDIFFUSE\n"
2065 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2066 "#endif\n"
2067 "\n"
2068 "#ifdef USESPECULAR\n"
2069 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2070 "# ifdef USECOLORMAPPING\n"
2071 "       gl_FragColor *= tex2;\n"
2072 "# endif\n"
2073 "# ifdef USEGLOW\n"
2074 "       gl_FragColor += tex2;\n"
2075 "# endif\n"
2076 "# ifdef USEVERTEXTEXTUREBLEND\n"
2077 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2078 "# endif\n"
2079 "#endif\n"
2080 "}\n"
2081 "#endif\n"
2082 "#else // !MODE_GENERIC\n"
2083 "\n"
2084 "\n"
2085 "\n"
2086 "\n"
2087 "#ifdef MODE_BLOOMBLUR\n"
2088 "#ifdef VERTEX_SHADER\n"
2089 "void main\n"
2090 "(\n"
2091 "float4 gl_Vertex : POSITION,\n"
2092 "uniform float4x4 ModelViewProjectionMatrix,\n"
2093 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2094 "out float4 gl_Position : POSITION,\n"
2095 "out float2 TexCoord : TEXCOORD0\n"
2096 ")\n"
2097 "{\n"
2098 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2099 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2100 "}\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef FRAGMENT_SHADER\n"
2104 "\n"
2105 "void main\n"
2106 "(\n"
2107 "float2 TexCoord : TEXCOORD0,\n"
2108 "uniform sampler2D Texture_First,\n"
2109 "uniform float4 BloomBlur_Parameters,\n"
2110 "out float4 gl_FragColor : COLOR\n"
2111 ")\n"
2112 "{\n"
2113 "       int i;\n"
2114 "       float2 tc = TexCoord;\n"
2115 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2116 "       tc += BloomBlur_Parameters.xy;\n"
2117 "       for (i = 1;i < SAMPLES;i++)\n"
2118 "       {\n"
2119 "               color += tex2D(Texture_First, tc).rgb;\n"
2120 "               tc += BloomBlur_Parameters.xy;\n"
2121 "       }\n"
2122 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2123 "}\n"
2124 "#endif\n"
2125 "#else // !MODE_BLOOMBLUR\n"
2126 "#ifdef MODE_REFRACTION\n"
2127 "#ifdef VERTEX_SHADER\n"
2128 "void main\n"
2129 "(\n"
2130 "float4 gl_Vertex : POSITION,\n"
2131 "uniform float4x4 ModelViewProjectionMatrix,\n"
2132 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2133 "uniform float4x4 TexMatrix,\n"
2134 "uniform float3 EyePosition,\n"
2135 "out float4 gl_Position : POSITION,\n"
2136 "out float2 TexCoord : TEXCOORD0,\n"
2137 "out float3 EyeVector : TEXCOORD1,\n"
2138 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2139 ")\n"
2140 "{\n"
2141 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2142 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2143 "       ModelViewProjectionPosition = gl_Position;\n"
2144 "}\n"
2145 "#endif\n"
2146 "\n"
2147 "#ifdef FRAGMENT_SHADER\n"
2148 "void main\n"
2149 "(\n"
2150 "float2 TexCoord : TEXCOORD0,\n"
2151 "float3 EyeVector : TEXCOORD1,\n"
2152 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2153 "uniform sampler2D Texture_Normal,\n"
2154 "uniform sampler2D Texture_Refraction,\n"
2155 "uniform sampler2D Texture_Reflection,\n"
2156 "uniform float4 DistortScaleRefractReflect,\n"
2157 "uniform float4 ScreenScaleRefractReflect,\n"
2158 "uniform float4 ScreenCenterRefractReflect,\n"
2159 "uniform float4 RefractColor,\n"
2160 "out float4 gl_FragColor : COLOR\n"
2161 ")\n"
2162 "{\n"
2163 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2164 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2165 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2166 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
2167 "       // FIXME temporary hack to detect the case that the reflection\n"
2168 "       // gets blackened at edges due to leaving the area that contains actual\n"
2169 "       // content.\n"
2170 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2171 "       // 'appening.\n"
2172 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2173 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2174 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2175 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2176 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2177 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2178 "}\n"
2179 "#endif\n"
2180 "#else // !MODE_REFRACTION\n"
2181 "\n"
2182 "\n"
2183 "\n"
2184 "\n"
2185 "#ifdef MODE_WATER\n"
2186 "#ifdef VERTEX_SHADER\n"
2187 "\n"
2188 "void main\n"
2189 "(\n"
2190 "float4 gl_Vertex : POSITION,\n"
2191 "uniform float4x4 ModelViewProjectionMatrix,\n"
2192 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2193 "uniform float4x4 TexMatrix,\n"
2194 "uniform float3 EyePosition,\n"
2195 "out float4 gl_Position : POSITION,\n"
2196 "out float2 TexCoord : TEXCOORD0,\n"
2197 "out float3 EyeVector : TEXCOORD1,\n"
2198 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2199 ")\n"
2200 "{\n"
2201 "       TexCoord = float2(mul(TexMatrix, gl_MultiTexCoord0));\n"
2202 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2203 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2204 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2205 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2206 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2207 "       ModelViewProjectionPosition = gl_Position;\n"
2208 "}\n"
2209 "#endif\n"
2210 "\n"
2211 "#ifdef FRAGMENT_SHADER\n"
2212 "void main\n"
2213 "(\n"
2214 "float2 TexCoord : TEXCOORD0,\n"
2215 "float3 EyeVector : TEXCOORD1,\n"
2216 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2217 "uniform sampler2D Texture_Normal,\n"
2218 "uniform sampler2D Texture_Refraction,\n"
2219 "uniform sampler2D Texture_Reflection,\n"
2220 "uniform float4 DistortScaleRefractReflect,\n"
2221 "uniform float4 ScreenScaleRefractReflect,\n"
2222 "uniform float4 ScreenCenterRefractReflect,\n"
2223 "uniform float4 RefractColor,\n"
2224 "uniform float4 ReflectColor,\n"
2225 "uniform float ReflectFactor,\n"
2226 "uniform float ReflectOffset,\n"
2227 "out float4 gl_FragColor : COLOR\n"
2228 ")\n"
2229 "{\n"
2230 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2231 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2232 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2233 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5))).xyxy * DistortScaleRefractReflect;\n"
2234 "       // FIXME temporary hack to detect the case that the reflection\n"
2235 "       // gets blackened at edges due to leaving the area that contains actual\n"
2236 "       // content.\n"
2237 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2238 "       // 'appening.\n"
2239 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2240 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2241 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2242 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2243 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2244 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2245 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2248 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2249 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2250 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_WATER\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "// 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"
2259 "\n"
2260 "// fragment shader specific:\n"
2261 "#ifdef FRAGMENT_SHADER\n"
2262 "\n"
2263 "#ifdef USEFOG\n"
2264 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler2D Texture_FogMask, sampler2D Texture_FogHeightTexture)\n"
2265 "{\n"
2266 "       float fogfrac;\n"
2267 "#ifdef USEFOGHEIGHTTEXTURE\n"
2268 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2269 "       fogfrac = fogheightpixel.a;\n"
2270 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2271 "#else\n"
2272 "# ifdef USEFOGOUTSIDE\n"
2273 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2274 "# else\n"
2275 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2276 "# endif\n"
2277 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2278 "#endif\n"
2279 "}\n"
2280 "#endif\n"
2281 "\n"
2282 "#ifdef USEOFFSETMAPPING\n"
2283 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler2D Texture_Normal)\n"
2284 "{\n"
2285 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2286 "       // 14 sample relief mapping: linear search and then binary search\n"
2287 "       // this basically steps forward a small amount repeatedly until it finds\n"
2288 "       // itself inside solid, then jitters forward and back using decreasing\n"
2289 "       // amounts to find the impact\n"
2290 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2291 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2292 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2293 "       float3 RT = float3(TexCoord, 1);\n"
2294 "       OffsetVector *= 0.1;\n"
2295 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2296 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2297 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2298 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2299 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2300 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2301 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2302 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2303 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2304 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2305 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2306 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2307 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2308 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2309 "       return RT.xy;\n"
2310 "#else\n"
2311 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2312 "       // this basically moves forward the full distance, and then backs up based\n"
2313 "       // on height of samples\n"
2314 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2315 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2316 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2317 "       TexCoord += OffsetVector;\n"
2318 "       OffsetVector *= 0.333;\n"
2319 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2320 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2321 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2322 "       return TexCoord;\n"
2323 "#endif\n"
2324 "}\n"
2325 "#endif // USEOFFSETMAPPING\n"
2326 "\n"
2327 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2328 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2329 "# ifdef USESHADOWMAPORTHO\n"
2330 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2331 "# else\n"
2332 "#  ifdef USESHADOWMAPVSDCT\n"
2333 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2334 "{\n"
2335 "       float3 adir = abs(dir);\n"
2336 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2337 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2338 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2339 "}\n"
2340 "#  else\n"
2341 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2342 "{\n"
2343 "       float3 adir = abs(dir);\n"
2344 "       float ma = adir.z;\n"
2345 "       float4 proj = float4(dir, 2.5);\n"
2346 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2347 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2348 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2349 "       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"
2350 "}\n"
2351 "#  endif\n"
2352 "# endif\n"
2353 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2354 "\n"
2355 "#ifdef USESHADOWMAPCUBE\n"
2356 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2357 "{\n"
2358 "    float3 adir = abs(dir);\n"
2359 "    return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2360 "}\n"
2361 "#endif\n"
2362 "\n"
2363 "# ifdef USESHADOWMAPRECT\n"
2364 "#ifdef USESHADOWMAPVSDCT\n"
2365 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2366 "#else\n"
2367 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2368 "#endif\n"
2369 "{\n"
2370 "#ifdef USESHADOWMAPVSDCT\n"
2371 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2372 "#else\n"
2373 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2374 "#endif\n"
2375 "       float f;\n"
2376 "#  ifdef USESHADOWSAMPLER\n"
2377 "\n"
2378 "#    ifdef USESHADOWMAPPCF\n"
2379 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2380 "    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"
2381 "#    else\n"
2382 "    f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2383 "#    endif\n"
2384 "\n"
2385 "#  else\n"
2386 "\n"
2387 "#    ifdef USESHADOWMAPPCF\n"
2388 "#      if USESHADOWMAPPCF > 1\n"
2389 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2390 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2391 "    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"
2392 "    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"
2393 "    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"
2394 "    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"
2395 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2396 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2397 "#      else\n"
2398 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2399 "    float2 offset = frac(shadowmaptc.xy);\n"
2400 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2401 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2402 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2403 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2404 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2405 "#      endif\n"
2406 "#    else\n"
2407 "    f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2408 "#    endif\n"
2409 "\n"
2410 "#  endif\n"
2411 "#  ifdef USESHADOWMAPORTHO\n"
2412 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2413 "#  else\n"
2414 "       return f;\n"
2415 "#  endif\n"
2416 "}\n"
2417 "# endif\n"
2418 "\n"
2419 "# ifdef USESHADOWMAP2D\n"
2420 "#ifdef USESHADOWMAPVSDCT\n"
2421 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2422 "#else\n"
2423 "float ShadowMapCompare(float3 dir, sampler2D Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2424 "#endif\n"
2425 "{\n"
2426 "#ifdef USESHADOWMAPVSDCT\n"
2427 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2428 "#else\n"
2429 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2430 "#endif\n"
2431 "    float f;\n"
2432 "\n"
2433 "#  ifdef USESHADOWSAMPLER\n"
2434 "#    ifdef USESHADOWMAPPCF\n"
2435 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, float3(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
2436 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2437 "    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"
2438 "#    else\n"
2439 "    f = shadow2D(Texture_ShadowMap2D, float3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
2440 "#    endif\n"
2441 "#  else\n"
2442 "#    ifdef USESHADOWMAPPCF\n"
2443 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2444 "#      ifdef GL_ARB_texture_gather\n"
2445 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec(x, y))\n"
2446 "#      else\n"
2447 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x,y)*ShadowMap_TextureScale)\n"
2448 "#      endif\n"
2449 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2450 "    center *= ShadowMap_TextureScale;\n"
2451 "    float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2452 "    float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2453 "    float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2454 "    float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2455 "    float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2456 "                lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2457 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2458 "#     else\n"
2459 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)  \n"
2460 "#      if USESHADOWMAPPCF > 1\n"
2461 "    float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2462 "    center *= ShadowMap_TextureScale;\n"
2463 "    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"
2464 "    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"
2465 "    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"
2466 "    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"
2467 "    float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2468 "    f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2469 "#      else\n"
2470 "    float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2471 "    float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2472 "    float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2473 "    float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2474 "    float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2475 "    f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25));\n"
2476 "#      endif\n"
2477 "#     endif\n"
2478 "#    else\n"
2479 "    f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2480 "#    endif\n"
2481 "#  endif\n"
2482 "#  ifdef USESHADOWMAPORTHO\n"
2483 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2484 "#  else\n"
2485 "       return f;\n"
2486 "#  endif\n"
2487 "}\n"
2488 "# endif\n"
2489 "\n"
2490 "# ifdef USESHADOWMAPCUBE\n"
2491 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2492 "{\n"
2493 "    // apply depth texture cubemap as light filter\n"
2494 "    float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2495 "    float f;\n"
2496 "#  ifdef USESHADOWSAMPLER\n"
2497 "    f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2498 "#  else\n"
2499 "    f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2500 "#  endif\n"
2501 "    return f;\n"
2502 "}\n"
2503 "# endif\n"
2504 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE)\n"
2505 "#endif // FRAGMENT_SHADER\n"
2506 "\n"
2507 "\n"
2508 "\n"
2509 "\n"
2510 "#ifdef MODE_DEFERREDGEOMETRY\n"
2511 "#ifdef VERTEX_SHADER\n"
2512 "void main\n"
2513 "(\n"
2514 "float4 gl_Vertex : POSITION,\n"
2515 "uniform float4x4 ModelViewProjectionMatrix,\n"
2516 "#ifdef USEVERTEXTEXTUREBLEND\n"
2517 "float4 gl_Color : COLOR0,\n"
2518 "#endif\n"
2519 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2520 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2521 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2522 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2523 "uniform float4x4 TexMatrix,\n"
2524 "#ifdef USEVERTEXTEXTUREBLEND\n"
2525 "uniform float4x4 BackgroundTexMatrix,\n"
2526 "#endif\n"
2527 "uniform float4x4 ModelViewMatrix,\n"
2528 "#ifdef USEOFFSETMAPPING\n"
2529 "uniform float3 EyePosition,\n"
2530 "#endif\n"
2531 "out float4 gl_Position : POSITION,\n"
2532 "out float4 gl_FrontColor : COLOR,\n"
2533 "out float4 TexCoordBoth : TEXCOORD0,\n"
2534 "#ifdef USEOFFSETMAPPING\n"
2535 "out float3 EyeVector : TEXCOORD2,\n"
2536 "#endif\n"
2537 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2538 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2539 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2540 ")\n"
2541 "{\n"
2542 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2543 "#ifdef USEVERTEXTEXTUREBLEND\n"
2544 "       gl_FrontColor = gl_Color;\n"
2545 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2546 "#endif\n"
2547 "\n"
2548 "       // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2554 "#endif\n"
2555 "\n"
2556 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 "}\n"
2561 "#endif // VERTEX_SHADER\n"
2562 "\n"
2563 "#ifdef FRAGMENT_SHADER\n"
2564 "void main\n"
2565 "(\n"
2566 "float4 TexCoordBoth : TEXCOORD0,\n"
2567 "float3 EyeVector : TEXCOORD2,\n"
2568 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2569 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2570 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2571 "uniform sampler2D Texture_Normal,\n"
2572 "#ifdef USEALPHAKILL\n"
2573 "uniform sampler2D Texture_Color,\n"
2574 "#endif\n"
2575 "uniform sampler2D Texture_Gloss,\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "uniform sampler2D Texture_SecondaryNormal,\n"
2578 "uniform sampler2D Texture_SecondaryGloss,\n"
2579 "#endif\n"
2580 "#ifdef USEOFFSETMAPPING\n"
2581 "uniform float OffsetMapping_Scale,\n"
2582 "#endif\n"
2583 "uniform half SpecularPower,\n"
2584 "out float4 gl_FragColor : COLOR\n"
2585 ")\n"
2586 "{\n"
2587 "       float2 TexCoord = TexCoordBoth.xy;\n"
2588 "#ifdef USEOFFSETMAPPING\n"
2589 "       // apply offsetmapping\n"
2590 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2591 "#define TexCoord TexCoordOffset\n"
2592 "#endif\n"
2593 "\n"
2594 "#ifdef USEALPHAKILL\n"
2595 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2596 "               discard;\n"
2597 "#endif\n"
2598 "\n"
2599 "#ifdef USEVERTEXTEXTUREBLEND\n"
2600 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2601 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2602 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2603 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2604 "#endif\n"
2605 "\n"
2606 "#ifdef USEVERTEXTEXTUREBLEND\n"
2607 "       float3 surfacenormal = lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend) - float3(0.5, 0.5, 0.5);\n"
2608 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2609 "#else\n"
2610 "       float3 surfacenormal = float3(tex2D(Texture_Normal, TexCoord)) - float3(0.5, 0.5, 0.5);\n"
2611 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2612 "#endif\n"
2613 "\n"
2614 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), 1);\n"
2615 "}\n"
2616 "#endif // FRAGMENT_SHADER\n"
2617 "#else // !MODE_DEFERREDGEOMETRY\n"
2618 "\n"
2619 "\n"
2620 "\n"
2621 "\n"
2622 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2623 "#ifdef VERTEX_SHADER\n"
2624 "void main\n"
2625 "(\n"
2626 "float4 gl_Vertex : POSITION,\n"
2627 "uniform float4x4 ModelViewProjectionMatrix,\n"
2628 "uniform float4x4 ModelViewMatrix,\n"
2629 "out float4 gl_Position : POSITION,\n"
2630 "out float4 ModelViewPosition : TEXCOORD0\n"
2631 ")\n"
2632 "{\n"
2633 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2634 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2635 "}\n"
2636 "#endif // VERTEX_SHADER\n"
2637 "\n"
2638 "#ifdef FRAGMENT_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "float2 Pixel : WPOS,\n"
2642 "float4 ModelViewPosition : TEXCOORD0,\n"
2643 "uniform float4x4 ViewToLight,\n"
2644 "uniform float2 ScreenToDepth, // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2645 "uniform float3 LightPosition,\n"
2646 "uniform half2 PixelToScreenTexCoord,\n"
2647 "uniform half3 DeferredColor_Ambient,\n"
2648 "uniform half3 DeferredColor_Diffuse,\n"
2649 "#ifdef USESPECULAR\n"
2650 "uniform half3 DeferredColor_Specular,\n"
2651 "uniform half SpecularPower,\n"
2652 "#endif\n"
2653 "uniform sampler2D Texture_Attenuation,\n"
2654 "uniform sampler2D Texture_ScreenDepth,\n"
2655 "uniform sampler2D Texture_ScreenNormalMap,\n"
2656 "\n"
2657 "#ifdef USECUBEFILTER\n"
2658 "uniform samplerCUBE Texture_Cube,\n"
2659 "#endif\n"
2660 "\n"
2661 "#ifdef USESHADOWMAPRECT\n"
2662 "# ifdef USESHADOWSAMPLER\n"
2663 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
2664 "# else\n"
2665 "uniform samplerRECT Texture_ShadowMapRect,\n"
2666 "# endif\n"
2667 "#endif\n"
2668 "\n"
2669 "#ifdef USESHADOWMAP2D\n"
2670 "# ifdef USESHADOWSAMPLER\n"
2671 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
2672 "# else\n"
2673 "uniform sampler2D Texture_ShadowMap2D,\n"
2674 "# endif\n"
2675 "#endif\n"
2676 "\n"
2677 "#ifdef USESHADOWMAPVSDCT\n"
2678 "uniform samplerCUBE Texture_CubeProjection,\n"
2679 "#endif\n"
2680 "\n"
2681 "#ifdef USESHADOWMAPCUBE\n"
2682 "# ifdef USESHADOWSAMPLER\n"
2683 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
2684 "# else\n"
2685 "uniform samplerCUBE Texture_ShadowMapCube,\n"
2686 "# endif\n"
2687 "#endif\n"
2688 "\n"
2689 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2690 "uniform float2 ShadowMap_TextureScale,\n"
2691 "uniform float4 ShadowMap_Parameters,\n"
2692 "#endif\n"
2693 "\n"
2694 "out float4 gl_FragData0 : COLOR0,\n"
2695 "out float4 gl_FragData1 : COLOR1\n"
2696 ")\n"
2697 "{\n"
2698 "       // calculate viewspace pixel position\n"
2699 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2700 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2701 "       float3 position;\n"
2702 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2703 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2704 "       // decode viewspace pixel normal\n"
2705 "       half4 normalmap = tex2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
2706 "       half3 surfacenormal = normalize(normalmap.rgb - half3(0.5,0.5,0.5));\n"
2707 "       // surfacenormal = pixel normal in viewspace\n"
2708 "       // LightVector = pixel to light in viewspace\n"
2709 "       // CubeVector = position in lightspace\n"
2710 "       // eyevector = pixel to view in viewspace\n"
2711 "       float3 CubeVector = float3(mul(ViewToLight, float4(position,1)));\n"
2712 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
2713 "#ifdef USEDIFFUSE\n"
2714 "       // calculate diffuse shading\n"
2715 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2716 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2717 "#endif\n"
2718 "#ifdef USESPECULAR\n"
2719 "       // calculate directional shading\n"
2720 "       float3 eyevector = position * -1.0;\n"
2721 "#  ifdef USEEXACTSPECULARMATH\n"
2722 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2723 "#  else\n"
2724 "       half3 specularnormal = normalize(lightnormal + half3(normalize(eyevector)));\n"
2725 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2726 "#  endif\n"
2727 "#endif\n"
2728 "\n"
2729 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2730 "       fade *= ShadowMapCompare(CubeVector,\n"
2731 "# if defined(USESHADOWMAP2D)\n"
2732 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2733 "# endif\n"
2734 "# if defined(USESHADOWMAPRECT)\n"
2735 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2736 "# endif\n"
2737 "# if defined(USESHADOWMAPCUBE)\n"
2738 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2739 "# endif\n"
2740 "\n"
2741 "#ifdef USESHADOWMAPVSDCT\n"
2742 ", Texture_CubeProjection\n"
2743 "#endif\n"
2744 "       );\n"
2745 "#endif\n"
2746 "\n"
2747 "#ifdef USEDIFFUSE\n"
2748 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2749 "#else\n"
2750 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2751 "#endif\n"
2752 "#ifdef USESPECULAR\n"
2753 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2754 "#else\n"
2755 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2756 "#endif\n"
2757 "\n"
2758 "# ifdef USECUBEFILTER\n"
2759 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2760 "       gl_FragData0.rgb *= cubecolor;\n"
2761 "       gl_FragData1.rgb *= cubecolor;\n"
2762 "# endif\n"
2763 "}\n"
2764 "#endif // FRAGMENT_SHADER\n"
2765 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2766 "\n"
2767 "\n"
2768 "\n"
2769 "\n"
2770 "#ifdef VERTEX_SHADER\n"
2771 "void main\n"
2772 "(\n"
2773 "float4 gl_Vertex : POSITION,\n"
2774 "uniform float4x4 ModelViewProjectionMatrix,\n"
2775 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2776 "float4 gl_Color : COLOR0,\n"
2777 "#endif\n"
2778 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2779 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2780 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2781 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2782 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2783 "\n"
2784 "uniform float3 EyePosition,\n"
2785 "uniform float4x4 TexMatrix,\n"
2786 "#ifdef USEVERTEXTEXTUREBLEND\n"
2787 "uniform float4x4 BackgroundTexMatrix,\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float4x4 ModelToLight,\n"
2791 "#endif\n"
2792 "#ifdef MODE_LIGHTSOURCE\n"
2793 "uniform float3 LightPosition,\n"
2794 "#endif\n"
2795 "#ifdef MODE_LIGHTDIRECTION\n"
2796 "uniform float3 LightDir,\n"
2797 "#endif\n"
2798 "uniform float4 FogPlane,\n"
2799 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2800 "uniform float3 LightPosition,\n"
2801 "#endif\n"
2802 "#ifdef USESHADOWMAPORTHO\n"
2803 "uniform float4x4 ShadowMapMatrix,\n"
2804 "#endif\n"
2805 "\n"
2806 "out float4 gl_FrontColor : COLOR,\n"
2807 "out float4 TexCoordBoth : TEXCOORD0,\n"
2808 "#ifdef USELIGHTMAP\n"
2809 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2810 "#endif\n"
2811 "#ifdef USEEYEVECTOR\n"
2812 "out float3 EyeVector : TEXCOORD2,\n"
2813 "#endif\n"
2814 "#ifdef USEREFLECTION\n"
2815 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2816 "#endif\n"
2817 "#ifdef USEFOG\n"
2818 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2819 "#endif\n"
2820 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2821 "out float3 LightVector : TEXCOORD1,\n"
2822 "#endif\n"
2823 "#ifdef MODE_LIGHTSOURCE\n"
2824 "out float3 CubeVector : TEXCOORD3,\n"
2825 "#endif\n"
2826 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2827 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2828 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2829 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2830 "#endif\n"
2831 "#ifdef USESHADOWMAPORTHO\n"
2832 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2833 "#endif\n"
2834 "out float4 gl_Position : POSITION\n"
2835 ")\n"
2836 "{\n"
2837 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2838 "       gl_FrontColor = gl_Color;\n"
2839 "#endif\n"
2840 "       // copy the surface texcoord\n"
2841 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2842 "#ifdef USEVERTEXTEXTUREBLEND\n"
2843 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2844 "#endif\n"
2845 "#ifdef USELIGHTMAP\n"
2846 "       TexCoordLightmap = float2(gl_MultiTexCoord4);\n"
2847 "#endif\n"
2848 "\n"
2849 "#ifdef MODE_LIGHTSOURCE\n"
2850 "       // transform vertex position into light attenuation/cubemap space\n"
2851 "       // (-1 to +1 across the light box)\n"
2852 "       CubeVector = float3(mul(ModelToLight, gl_Vertex));\n"
2853 "\n"
2854 "# ifdef USEDIFFUSE\n"
2855 "       // transform unnormalized light direction into tangent space\n"
2856 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2857 "       //  normalize it per pixel)\n"
2858 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2859 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2860 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2861 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2862 "# endif\n"
2863 "#endif\n"
2864 "\n"
2865 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2866 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2867 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2868 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2869 "#endif\n"
2870 "\n"
2871 "       // transform unnormalized eye direction into tangent space\n"
2872 "#ifdef USEEYEVECTOR\n"
2873 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2874 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2875 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2876 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2877 "#endif\n"
2878 "\n"
2879 "#ifdef USEFOG\n"
2880 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2881 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2882 "#endif\n"
2883 "\n"
2884 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2885 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2886 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2887 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2888 "#endif\n"
2889 "\n"
2890 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2892 "\n"
2893 "#ifdef USESHADOWMAPORTHO\n"
2894 "       ShadowMapTC = float3(mul(ShadowMapMatrix, gl_Position));\n"
2895 "#endif\n"
2896 "\n"
2897 "#ifdef USEREFLECTION\n"
2898 "       ModelViewProjectionPosition = gl_Position;\n"
2899 "#endif\n"
2900 "}\n"
2901 "#endif // VERTEX_SHADER\n"
2902 "\n"
2903 "\n"
2904 "\n"
2905 "\n"
2906 "#ifdef FRAGMENT_SHADER\n"
2907 "void main\n"
2908 "(\n"
2909 "#ifdef USEDEFERREDLIGHTMAP\n"
2910 "float2 Pixel : WPOS,\n"
2911 "#endif\n"
2912 "float4 gl_FrontColor : COLOR,\n"
2913 "float4 TexCoordBoth : TEXCOORD0,\n"
2914 "#ifdef USELIGHTMAP\n"
2915 "float2 TexCoordLightmap : TEXCOORD1,\n"
2916 "#endif\n"
2917 "#ifdef USEEYEVECTOR\n"
2918 "float3 EyeVector : TEXCOORD2,\n"
2919 "#endif\n"
2920 "#ifdef USEREFLECTION\n"
2921 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2922 "#endif\n"
2923 "#ifdef USEFOG\n"
2924 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2925 "#endif\n"
2926 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2927 "float3 LightVector : TEXCOORD1,\n"
2928 "#endif\n"
2929 "#ifdef MODE_LIGHTSOURCE\n"
2930 "float3 CubeVector : TEXCOORD3,\n"
2931 "#endif\n"
2932 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2933 "float4 ModelViewPosition : TEXCOORD0,\n"
2934 "#endif\n"
2935 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2936 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2937 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2938 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2939 "#endif\n"
2940 "#ifdef USESHADOWMAPORTHO\n"
2941 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2942 "#endif\n"
2943 "\n"
2944 "uniform sampler2D Texture_Normal,\n"
2945 "uniform sampler2D Texture_Color,\n"
2946 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2947 "uniform sampler2D Texture_Gloss,\n"
2948 "#endif\n"
2949 "#ifdef USEGLOW\n"
2950 "uniform sampler2D Texture_Glow,\n"
2951 "#endif\n"
2952 "#ifdef USEVERTEXTEXTUREBLEND\n"
2953 "uniform sampler2D Texture_SecondaryNormal,\n"
2954 "uniform sampler2D Texture_SecondaryColor,\n"
2955 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2956 "uniform sampler2D Texture_SecondaryGloss,\n"
2957 "#endif\n"
2958 "#ifdef USEGLOW\n"
2959 "uniform sampler2D Texture_SecondaryGlow,\n"
2960 "#endif\n"
2961 "#endif\n"
2962 "#ifdef USECOLORMAPPING\n"
2963 "uniform sampler2D Texture_Pants,\n"
2964 "uniform sampler2D Texture_Shirt,\n"
2965 "#endif\n"
2966 "#ifdef USEFOG\n"
2967 "uniform sampler2D Texture_FogHeightTexture,\n"
2968 "uniform sampler2D Texture_FogMask,\n"
2969 "#endif\n"
2970 "#ifdef USELIGHTMAP\n"
2971 "uniform sampler2D Texture_Lightmap,\n"
2972 "#endif\n"
2973 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2974 "uniform sampler2D Texture_Deluxemap,\n"
2975 "#endif\n"
2976 "#ifdef USEREFLECTION\n"
2977 "uniform sampler2D Texture_Reflection,\n"
2978 "#endif\n"
2979 "\n"
2980 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2981 "uniform sampler2D Texture_ScreenDepth,\n"
2982 "uniform sampler2D Texture_ScreenNormalMap,\n"
2983 "#endif\n"
2984 "#ifdef USEDEFERREDLIGHTMAP\n"
2985 "uniform sampler2D Texture_ScreenDiffuse,\n"
2986 "uniform sampler2D Texture_ScreenSpecular,\n"
2987 "#endif\n"
2988 "\n"
2989 "#ifdef USECOLORMAPPING\n"
2990 "uniform half3 Color_Pants,\n"
2991 "uniform half3 Color_Shirt,\n"
2992 "#endif\n"
2993 "#ifdef USEFOG\n"
2994 "uniform float3 FogColor,\n"
2995 "uniform float FogRangeRecip,\n"
2996 "uniform float FogPlaneViewDist,\n"
2997 "uniform float FogHeightFade,\n"
2998 "#endif\n"
2999 "\n"
3000 "#ifdef USEOFFSETMAPPING\n"
3001 "uniform float OffsetMapping_Scale,\n"
3002 "#endif\n"
3003 "\n"
3004 "#ifdef USEDEFERREDLIGHTMAP\n"
3005 "uniform half2 PixelToScreenTexCoord,\n"
3006 "uniform half3 DeferredMod_Diffuse,\n"
3007 "uniform half3 DeferredMod_Specular,\n"
3008 "#endif\n"
3009 "uniform half3 Color_Ambient,\n"
3010 "uniform half3 Color_Diffuse,\n"
3011 "uniform half3 Color_Specular,\n"
3012 "uniform half SpecularPower,\n"
3013 "#ifdef USEGLOW\n"
3014 "uniform half3 Color_Glow,\n"
3015 "#endif\n"
3016 "uniform half Alpha,\n"
3017 "#ifdef USEREFLECTION\n"
3018 "uniform float4 DistortScaleRefractReflect,\n"
3019 "uniform float4 ScreenScaleRefractReflect,\n"
3020 "uniform float4 ScreenCenterRefractReflect,\n"
3021 "uniform half4 ReflectColor,\n"
3022 "#endif\n"
3023 "#ifdef USEREFLECTCUBE\n"
3024 "uniform float4x4 ModelToReflectCube,\n"
3025 "uniform sampler2D Texture_ReflectMask,\n"
3026 "uniform samplerCUBE Texture_ReflectCube,\n"
3027 "#endif\n"
3028 "#ifdef MODE_LIGHTDIRECTION\n"
3029 "uniform half3 LightColor,\n"
3030 "#endif\n"
3031 "#ifdef MODE_LIGHTSOURCE\n"
3032 "uniform half3 LightColor,\n"
3033 "#endif\n"
3034 "\n"
3035 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3036 "uniform sampler2D Texture_Attenuation,\n"
3037 "uniform samplerCUBE Texture_Cube,\n"
3038 "#endif\n"
3039 "\n"
3040 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3041 "\n"
3042 "#ifdef USESHADOWMAPRECT\n"
3043 "# ifdef USESHADOWSAMPLER\n"
3044 "uniform samplerRECTShadow Texture_ShadowMapRect,\n"
3045 "# else\n"
3046 "uniform samplerRECT Texture_ShadowMapRect,\n"
3047 "# endif\n"
3048 "#endif\n"
3049 "\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler2DShadow Texture_ShadowMap2D,\n"
3053 "# else\n"
3054 "uniform sampler2D Texture_ShadowMap2D,\n"
3055 "# endif\n"
3056 "#endif\n"
3057 "\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection,\n"
3060 "#endif\n"
3061 "\n"
3062 "#ifdef USESHADOWMAPCUBE\n"
3063 "# ifdef USESHADOWSAMPLER\n"
3064 "uniform samplerCUBEShadow Texture_ShadowMapCube,\n"
3065 "# else\n"
3066 "uniform samplerCUBE Texture_ShadowMapCube,\n"
3067 "# endif\n"
3068 "#endif\n"
3069 "\n"
3070 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3071 "uniform float2 ShadowMap_TextureScale,\n"
3072 "uniform float4 ShadowMap_Parameters,\n"
3073 "#endif\n"
3074 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3075 "\n"
3076 "out float4 gl_FragColor : COLOR\n"
3077 ")\n"
3078 "{\n"
3079 "       float2 TexCoord = TexCoordBoth.xy;\n"
3080 "#ifdef USEVERTEXTEXTUREBLEND\n"
3081 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3082 "#endif\n"
3083 "#ifdef USEOFFSETMAPPING\n"
3084 "       // apply offsetmapping\n"
3085 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3086 "#define TexCoord TexCoordOffset\n"
3087 "#endif\n"
3088 "\n"
3089 "       // combine the diffuse textures (base, pants, shirt)\n"
3090 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3091 "#ifdef USEALPHAKILL\n"
3092 "       if (color.a < 0.5)\n"
3093 "               discard;\n"
3094 "#endif\n"
3095 "       color.a *= Alpha;\n"
3096 "#ifdef USECOLORMAPPING\n"
3097 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord)) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
3098 "#endif\n"
3099 "#ifdef USEVERTEXTEXTUREBLEND\n"
3100 "       float terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3101 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3102 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3103 "       color.rgb = half3(lerp(float3(tex2D(Texture_SecondaryColor, TexCoord2)), float3(color.rgb), terrainblend));\n"
3104 "       color.a = 1.0;\n"
3105 "       //color = lerp(half4(1, 0, 0, 1), color, terrainblend);\n"
3106 "#endif\n"
3107 "\n"
3108 "       // get the surface normal\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       half3 surfacenormal = normalize(half3(lerp(float3(tex2D(Texture_SecondaryNormal, TexCoord2)), float3(tex2D(Texture_Normal, TexCoord)), terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3111 "#else\n"
3112 "       half3 surfacenormal = normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5, 0.5, 0.5));\n"
3113 "#endif\n"
3114 "\n"
3115 "       // get the material colors\n"
3116 "       half3 diffusetex = color.rgb;\n"
3117 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3118 "# ifdef USEVERTEXTEXTUREBLEND\n"
3119 "       half4 glosstex = half4(lerp(float4(tex2D(Texture_SecondaryGloss, TexCoord2)), float4(tex2D(Texture_Gloss, TexCoord)), terrainblend));\n"
3120 "# else\n"
3121 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3122 "# endif\n"
3123 "#endif\n"
3124 "\n"
3125 "#ifdef USEREFLECTCUBE\n"
3126 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3127 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3128 "       float3 ReflectCubeTexCoord = float3(mul(ModelToReflectCube, float4(ModelReflectVector, 0)));\n"
3129 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord)) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord));\n"
3130 "#endif\n"
3131 "\n"
3132 "\n"
3133 "\n"
3134 "\n"
3135 "#ifdef MODE_LIGHTSOURCE\n"
3136 "       // light source\n"
3137 "#ifdef USEDIFFUSE\n"
3138 "       half3 lightnormal = half3(normalize(LightVector));\n"
3139 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3140 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3141 "#ifdef USESPECULAR\n"
3142 "#ifdef USEEXACTSPECULARMATH\n"
3143 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3144 "#else\n"
3145 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3146 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3147 "#endif\n"
3148 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3149 "#endif\n"
3150 "#else\n"
3151 "       color.rgb = diffusetex * Color_Ambient;\n"
3152 "#endif\n"
3153 "       color.rgb *= LightColor;\n"
3154 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)));\n"
3155 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3156 "       color.rgb *= ShadowMapCompare(CubeVector,\n"
3157 "# if defined(USESHADOWMAP2D)\n"
3158 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3159 "# endif\n"
3160 "# if defined(USESHADOWMAPRECT)\n"
3161 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3162 "# endif\n"
3163 "# if defined(USESHADOWMAPCUBE)\n"
3164 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3165 "# endif\n"
3166 "\n"
3167 "#ifdef USESHADOWMAPVSDCT\n"
3168 ", Texture_CubeProjection\n"
3169 "#endif\n"
3170 "       );\n"
3171 "\n"
3172 "#endif\n"
3173 "# ifdef USECUBEFILTER\n"
3174 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector));\n"
3175 "# endif\n"
3176 "#endif // MODE_LIGHTSOURCE\n"
3177 "\n"
3178 "\n"
3179 "\n"
3180 "\n"
3181 "#ifdef MODE_LIGHTDIRECTION\n"
3182 "#define SHADING\n"
3183 "#ifdef USEDIFFUSE\n"
3184 "       half3 lightnormal = half3(normalize(LightVector));\n"
3185 "#endif\n"
3186 "#define lightcolor LightColor\n"
3187 "#endif // MODE_LIGHTDIRECTION\n"
3188 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3189 "#define SHADING\n"
3190 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3191 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3192 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3193 "       // convert modelspace light vector to tangentspace\n"
3194 "       half3 lightnormal;\n"
3195 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3196 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3197 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3198 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3199 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3200 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3201 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3202 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3203 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3204 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3205 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3206 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3207 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3208 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3209 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3210 "#define SHADING\n"
3211 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3212 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3213 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap));\n"
3214 "#endif\n"
3215 "\n"
3216 "\n"
3217 "\n"
3218 "\n"
3219 "#ifdef MODE_LIGHTMAP\n"
3220 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
3221 "#endif // MODE_LIGHTMAP\n"
3222 "#ifdef MODE_VERTEXCOLOR\n"
3223 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3224 "#endif // MODE_VERTEXCOLOR\n"
3225 "#ifdef MODE_FLATCOLOR\n"
3226 "       color.rgb = diffusetex * Color_Ambient;\n"
3227 "#endif // MODE_FLATCOLOR\n"
3228 "\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "#ifdef SHADING\n"
3233 "# ifdef USEDIFFUSE\n"
3234 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3235 "#  ifdef USESPECULAR\n"
3236 "#   ifdef USEEXACTSPECULARMATH\n"
3237 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
3238 "#   else\n"
3239 "       half3 specularnormal = normalize(lightnormal + half3(normalize(EyeVector)));\n"
3240 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
3241 "#   endif\n"
3242 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3243 "#  else\n"
3244 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3245 "#  endif\n"
3246 "# else\n"
3247 "       color.rgb = diffusetex * Color_Ambient;\n"
3248 "# endif\n"
3249 "#endif\n"
3250 "\n"
3251 "#ifdef USESHADOWMAPORTHO\n"
3252 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3253 "# if defined(USESHADOWMAP2D)\n"
3254 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3255 "# endif\n"
3256 "# if defined(USESHADOWMAPRECT)\n"
3257 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3258 "# endif\n"
3259 "       );\n"
3260 "#endif\n"
3261 "\n"
3262 "#ifdef USEDEFERREDLIGHTMAP\n"
3263 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3264 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
3265 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
3266 "#endif\n"
3267 "\n"
3268 "#ifdef USEGLOW\n"
3269 "#ifdef USEVERTEXTEXTUREBLEND\n"
3270 "       color.rgb += lerp(half3(tex2D(Texture_SecondaryGlow, TexCoord2)), half3(tex2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
3271 "#else\n"
3272 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
3273 "#endif\n"
3274 "#endif\n"
3275 "\n"
3276 "#ifdef USEFOG\n"
3277 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3278 "#endif\n"
3279 "\n"
3280 "       // 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"
3281 "#ifdef USEREFLECTION\n"
3282 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3283 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3284 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3285 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord)) - half3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
3286 "       // FIXME temporary hack to detect the case that the reflection\n"
3287 "       // gets blackened at edges due to leaving the area that contains actual\n"
3288 "       // content.\n"
3289 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3290 "       // 'appening.\n"
3291 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3292 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3293 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3294 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3295 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3296 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
3297 "#endif\n"
3298 "\n"
3299 "       gl_FragColor = float4(color);\n"
3300 "}\n"
3301 "#endif // FRAGMENT_SHADER\n"
3302 "\n"
3303 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3304 "#endif // !MODE_DEFERREDGEOMETRY\n"
3305 "#endif // !MODE_WATER\n"
3306 "#endif // !MODE_REFRACTION\n"
3307 "#endif // !MODE_BLOOMBLUR\n"
3308 "#endif // !MODE_GENERIC\n"
3309 "#endif // !MODE_POSTPROCESS\n"
3310 "#endif // !MODE_SHOWDEPTH\n"
3311 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3312 ;
3313
3314 char *glslshaderstring = NULL;
3315 char *cgshaderstring = NULL;
3316
3317 //=======================================================================================================================================================
3318
3319 typedef struct shaderpermutationinfo_s
3320 {
3321         const char *pretext;
3322         const char *name;
3323 }
3324 shaderpermutationinfo_t;
3325
3326 typedef struct shadermodeinfo_s
3327 {
3328         const char *vertexfilename;
3329         const char *geometryfilename;
3330         const char *fragmentfilename;
3331         const char *pretext;
3332         const char *name;
3333 }
3334 shadermodeinfo_t;
3335
3336 typedef enum shaderpermutation_e
3337 {
3338         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3339         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3340         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3341         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3342         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3343         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3344         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3345         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3346         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3347         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3348         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3349         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3350         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3351         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3352         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3353         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3354         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3355         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3356         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3357         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3358         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3359         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3360         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3361         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3362         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3363         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3364         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3365         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3366         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3367         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3368         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3369 }
3370 shaderpermutation_t;
3371
3372 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3373 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3374 {
3375         {"#define USEDIFFUSE\n", " diffuse"},
3376         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3377         {"#define USEVIEWTINT\n", " viewtint"},
3378         {"#define USECOLORMAPPING\n", " colormapping"},
3379         {"#define USESATURATION\n", " saturation"},
3380         {"#define USEFOGINSIDE\n", " foginside"},
3381         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3382         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3383         {"#define USEGAMMARAMPS\n", " gammaramps"},
3384         {"#define USECUBEFILTER\n", " cubefilter"},
3385         {"#define USEGLOW\n", " glow"},
3386         {"#define USEBLOOM\n", " bloom"},
3387         {"#define USESPECULAR\n", " specular"},
3388         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3389         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3390         {"#define USEREFLECTION\n", " reflection"},
3391         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3392         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3393         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3394         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3395         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3396         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3397         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3398         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3399         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3400         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3401         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3402         {"#define USEALPHAKILL\n", " alphakill"},
3403         {"#define USEREFLECTCUBE\n", " reflectcube"},
3404 };
3405
3406 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3407 typedef enum shadermode_e
3408 {
3409         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3410         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3411         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3412         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3413         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3414         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3415         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3416         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3417         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3418         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3419         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3420         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3421         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3422         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3423         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3424         SHADERMODE_COUNT
3425 }
3426 shadermode_t;
3427
3428 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3429 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3430 {
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3433         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3434         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3435         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3436         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3437         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3438         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3439         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3440         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3441         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3442         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3443         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3444         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3445         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3446 };
3447
3448 #ifdef SUPPORTCG
3449 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3450 {
3451         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3452         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3453         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3454         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3455         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3456         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3457         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3458         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3459         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3460         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3461         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3462         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3463         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3464         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3465         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3466 };
3467 #endif
3468
3469 struct r_glsl_permutation_s;
3470 typedef struct r_glsl_permutation_s
3471 {
3472         /// hash lookup data
3473         struct r_glsl_permutation_s *hashnext;
3474         unsigned int mode;
3475         unsigned int permutation;
3476
3477         /// indicates if we have tried compiling this permutation already
3478         qboolean compiled;
3479         /// 0 if compilation failed
3480         int program;
3481         /// locations of detected uniforms in program object, or -1 if not found
3482         int loc_Texture_First;
3483         int loc_Texture_Second;
3484         int loc_Texture_GammaRamps;
3485         int loc_Texture_Normal;
3486         int loc_Texture_Color;
3487         int loc_Texture_Gloss;
3488         int loc_Texture_Glow;
3489         int loc_Texture_SecondaryNormal;
3490         int loc_Texture_SecondaryColor;
3491         int loc_Texture_SecondaryGloss;
3492         int loc_Texture_SecondaryGlow;
3493         int loc_Texture_Pants;
3494         int loc_Texture_Shirt;
3495         int loc_Texture_FogHeightTexture;
3496         int loc_Texture_FogMask;
3497         int loc_Texture_Lightmap;
3498         int loc_Texture_Deluxemap;
3499         int loc_Texture_Attenuation;
3500         int loc_Texture_Cube;
3501         int loc_Texture_Refraction;
3502         int loc_Texture_Reflection;
3503         int loc_Texture_ShadowMapRect;
3504         int loc_Texture_ShadowMapCube;
3505         int loc_Texture_ShadowMap2D;
3506         int loc_Texture_CubeProjection;
3507         int loc_Texture_ScreenDepth;
3508         int loc_Texture_ScreenNormalMap;
3509         int loc_Texture_ScreenDiffuse;
3510         int loc_Texture_ScreenSpecular;
3511         int loc_Texture_ReflectMask;
3512         int loc_Texture_ReflectCube;
3513         int loc_Alpha;
3514         int loc_BloomBlur_Parameters;
3515         int loc_ClientTime;
3516         int loc_Color_Ambient;
3517         int loc_Color_Diffuse;
3518         int loc_Color_Specular;
3519         int loc_Color_Glow;
3520         int loc_Color_Pants;
3521         int loc_Color_Shirt;
3522         int loc_DeferredColor_Ambient;
3523         int loc_DeferredColor_Diffuse;
3524         int loc_DeferredColor_Specular;
3525         int loc_DeferredMod_Diffuse;
3526         int loc_DeferredMod_Specular;
3527         int loc_DistortScaleRefractReflect;
3528         int loc_EyePosition;
3529         int loc_FogColor;
3530         int loc_FogHeightFade;
3531         int loc_FogPlane;
3532         int loc_FogPlaneViewDist;
3533         int loc_FogRangeRecip;
3534         int loc_LightColor;
3535         int loc_LightDir;
3536         int loc_LightPosition;
3537         int loc_OffsetMapping_Scale;
3538         int loc_PixelSize;
3539         int loc_ReflectColor;
3540         int loc_ReflectFactor;
3541         int loc_ReflectOffset;
3542         int loc_RefractColor;
3543         int loc_Saturation;
3544         int loc_ScreenCenterRefractReflect;
3545         int loc_ScreenScaleRefractReflect;
3546         int loc_ScreenToDepth;
3547         int loc_ShadowMap_Parameters;
3548         int loc_ShadowMap_TextureScale;
3549         int loc_SpecularPower;
3550         int loc_UserVec1;
3551         int loc_UserVec2;
3552         int loc_UserVec3;
3553         int loc_UserVec4;
3554         int loc_ViewTintColor;
3555         int loc_ViewToLight;
3556         int loc_ModelToLight;
3557         int loc_TexMatrix;
3558         int loc_BackgroundTexMatrix;
3559         int loc_ModelViewProjectionMatrix;
3560         int loc_ModelViewMatrix;
3561         int loc_PixelToScreenTexCoord;
3562         int loc_ModelToReflectCube;
3563         int loc_ShadowMapMatrix;        
3564 }
3565 r_glsl_permutation_t;
3566
3567 #define SHADERPERMUTATION_HASHSIZE 256
3568
3569 /// information about each possible shader permutation
3570 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3571 /// currently selected permutation
3572 r_glsl_permutation_t *r_glsl_permutation;
3573 /// storage for permutations linked in the hash table
3574 memexpandablearray_t r_glsl_permutationarray;
3575
3576 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3577 {
3578         //unsigned int hashdepth = 0;
3579         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3580         r_glsl_permutation_t *p;
3581         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3582         {
3583                 if (p->mode == mode && p->permutation == permutation)
3584                 {
3585                         //if (hashdepth > 10)
3586                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3587                         return p;
3588                 }
3589                 //hashdepth++;
3590         }
3591         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3592         p->mode = mode;
3593         p->permutation = permutation;
3594         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3595         r_glsl_permutationhash[mode][hashindex] = p;
3596         //if (hashdepth > 10)
3597         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3598         return p;
3599 }
3600
3601 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3602 {
3603         char *shaderstring;
3604         if (!filename || !filename[0])
3605                 return NULL;
3606         if (!strcmp(filename, "glsl/default.glsl"))
3607         {
3608                 if (!glslshaderstring)
3609                 {
3610                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3611                         if (glslshaderstring)
3612                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3613                         else
3614                                 glslshaderstring = (char *)builtinshaderstring;
3615                 }
3616                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3617                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3618                 return shaderstring;
3619         }
3620         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3621         if (shaderstring)
3622         {
3623                 if (printfromdisknotice)
3624                         Con_DPrintf("from disk %s... ", filename);
3625                 return shaderstring;
3626         }
3627         return shaderstring;
3628 }
3629
3630 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3631 {
3632         int i;
3633         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3634         int vertstrings_count = 0;
3635         int geomstrings_count = 0;
3636         int fragstrings_count = 0;
3637         char *vertexstring, *geometrystring, *fragmentstring;
3638         const char *vertstrings_list[32+3];
3639         const char *geomstrings_list[32+3];
3640         const char *fragstrings_list[32+3];
3641         char permutationname[256];
3642
3643         if (p->compiled)
3644                 return;
3645         p->compiled = true;
3646         p->program = 0;
3647
3648         permutationname[0] = 0;
3649         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3650         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3651         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3652
3653         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3654
3655         // the first pretext is which type of shader to compile as
3656         // (later these will all be bound together as a program object)
3657         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3658         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3659         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3660
3661         // the second pretext is the mode (for example a light source)
3662         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3663         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3664         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3665         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3666
3667         // now add all the permutation pretexts
3668         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3669         {
3670                 if (permutation & (1<<i))
3671                 {
3672                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3673                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3674                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3675                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3676                 }
3677                 else
3678                 {
3679                         // keep line numbers correct
3680                         vertstrings_list[vertstrings_count++] = "\n";
3681                         geomstrings_list[geomstrings_count++] = "\n";
3682                         fragstrings_list[fragstrings_count++] = "\n";
3683                 }
3684         }
3685
3686         // now append the shader text itself
3687         vertstrings_list[vertstrings_count++] = vertexstring;
3688         geomstrings_list[geomstrings_count++] = geometrystring;
3689         fragstrings_list[fragstrings_count++] = fragmentstring;
3690
3691         // if any sources were NULL, clear the respective list
3692         if (!vertexstring)
3693                 vertstrings_count = 0;
3694         if (!geometrystring)
3695                 geomstrings_count = 0;
3696         if (!fragmentstring)
3697                 fragstrings_count = 0;
3698
3699         // compile the shader program
3700         if (vertstrings_count + geomstrings_count + fragstrings_count)
3701                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3702         if (p->program)
3703         {
3704                 CHECKGLERROR
3705                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3706                 // look up all the uniform variable names we care about, so we don't
3707                 // have to look them up every time we set them
3708
3709                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3710                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3711                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3712                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3713                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3714                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3715                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3716                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3717                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3718                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3719                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3720                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3721                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3722                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3723                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3724                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3725                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3726                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3727                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3728                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3729                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3730                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3731                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3732                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3733                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3734                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3735                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3736                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3737                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3738                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3739                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3740                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3741                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3742                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3743                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3744                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3745                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3746                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3747                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3748                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3749                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3750                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3751                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3752                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3753                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3754                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3755                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3756                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3757                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3758                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3759                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3760                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3761                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3762                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3763                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3764                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3765                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3766                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3767                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3768                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3769                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3770                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3771                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3772                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3773                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3774                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3775                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3776                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3777                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3778                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3779                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3780                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3781                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3782                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3783                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3784                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3785                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3786                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3787                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3788                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3789                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3790                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");            
3791                 // initialize the samplers to refer to the texture units we use
3792                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3793                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3794                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3795                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3796                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3797                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3798                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3799                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3800                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3801                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3802                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3803                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3804                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3805                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3806                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3807                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3808                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3809                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3810                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3811                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3812                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3813                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3814                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3815                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3816                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3817                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3818                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3819                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3820                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3821                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3822                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3823                 CHECKGLERROR
3824                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3825         }
3826         else
3827                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3828
3829         // free the strings
3830         if (vertexstring)
3831                 Mem_Free(vertexstring);
3832         if (geometrystring)
3833                 Mem_Free(geometrystring);
3834         if (fragmentstring)
3835                 Mem_Free(fragmentstring);
3836 }
3837
3838 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3839 {
3840         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3841         if (r_glsl_permutation != perm)
3842         {
3843                 r_glsl_permutation = perm;
3844                 if (!r_glsl_permutation->program)
3845                 {
3846                         if (!r_glsl_permutation->compiled)
3847                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3848                         if (!r_glsl_permutation->program)
3849                         {
3850                                 // remove features until we find a valid permutation
3851                                 int i;
3852                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3853                                 {
3854                                         // reduce i more quickly whenever it would not remove any bits
3855                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3856                                         if (!(permutation & j))
3857                                                 continue;
3858                                         permutation -= j;
3859                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3860                                         if (!r_glsl_permutation->compiled)
3861                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3862                                         if (r_glsl_permutation->program)
3863                                                 break;
3864                                 }
3865                                 if (i >= SHADERPERMUTATION_COUNT)
3866                                 {
3867                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3868                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3869                                         qglUseProgramObjectARB(0);CHECKGLERROR
3870                                         return; // no bit left to clear, entire mode is broken
3871                                 }
3872                         }
3873                 }
3874                 CHECKGLERROR
3875                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3876         }
3877         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3878         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3879         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3880 }
3881
3882 #ifdef SUPPORTCG
3883 #include <Cg/cgGL.h>
3884 struct r_cg_permutation_s;
3885 typedef struct r_cg_permutation_s
3886 {
3887         /// hash lookup data
3888         struct r_cg_permutation_s *hashnext;
3889         unsigned int mode;
3890         unsigned int permutation;
3891
3892         /// indicates if we have tried compiling this permutation already
3893         qboolean compiled;
3894         /// 0 if compilation failed
3895         CGprogram vprogram;
3896         CGprogram fprogram;
3897         /// locations of detected parameters in programs, or NULL if not found
3898         CGparameter vp_EyePosition;
3899         CGparameter vp_FogPlane;
3900         CGparameter vp_LightDir;
3901         CGparameter vp_LightPosition;
3902         CGparameter vp_ModelToLight;
3903         CGparameter vp_TexMatrix;
3904         CGparameter vp_BackgroundTexMatrix;
3905         CGparameter vp_ModelViewProjectionMatrix;
3906         CGparameter vp_ModelViewMatrix;
3907         CGparameter vp_ShadowMapMatrix;
3908
3909         CGparameter fp_Texture_First;
3910         CGparameter fp_Texture_Second;
3911         CGparameter fp_Texture_GammaRamps;
3912         CGparameter fp_Texture_Normal;
3913         CGparameter fp_Texture_Color;
3914         CGparameter fp_Texture_Gloss;
3915         CGparameter fp_Texture_Glow;
3916         CGparameter fp_Texture_SecondaryNormal;
3917         CGparameter fp_Texture_SecondaryColor;
3918         CGparameter fp_Texture_SecondaryGloss;
3919         CGparameter fp_Texture_SecondaryGlow;
3920         CGparameter fp_Texture_Pants;
3921         CGparameter fp_Texture_Shirt;
3922         CGparameter fp_Texture_FogHeightTexture;
3923         CGparameter fp_Texture_FogMask;
3924         CGparameter fp_Texture_Lightmap;
3925         CGparameter fp_Texture_Deluxemap;
3926         CGparameter fp_Texture_Attenuation;
3927         CGparameter fp_Texture_Cube;
3928         CGparameter fp_Texture_Refraction;
3929         CGparameter fp_Texture_Reflection;
3930         CGparameter fp_Texture_ShadowMapRect;
3931         CGparameter fp_Texture_ShadowMapCube;
3932         CGparameter fp_Texture_ShadowMap2D;
3933         CGparameter fp_Texture_CubeProjection;
3934         CGparameter fp_Texture_ScreenDepth;
3935         CGparameter fp_Texture_ScreenNormalMap;
3936         CGparameter fp_Texture_ScreenDiffuse;
3937         CGparameter fp_Texture_ScreenSpecular;
3938         CGparameter fp_Texture_ReflectMask;
3939         CGparameter fp_Texture_ReflectCube;
3940         CGparameter fp_Alpha;
3941         CGparameter fp_BloomBlur_Parameters;
3942         CGparameter fp_ClientTime;
3943         CGparameter fp_Color_Ambient;
3944         CGparameter fp_Color_Diffuse;
3945         CGparameter fp_Color_Specular;
3946         CGparameter fp_Color_Glow;
3947         CGparameter fp_Color_Pants;
3948         CGparameter fp_Color_Shirt;
3949         CGparameter fp_DeferredColor_Ambient;
3950         CGparameter fp_DeferredColor_Diffuse;
3951         CGparameter fp_DeferredColor_Specular;
3952         CGparameter fp_DeferredMod_Diffuse;
3953         CGparameter fp_DeferredMod_Specular;
3954         CGparameter fp_DistortScaleRefractReflect;
3955         CGparameter fp_EyePosition;
3956         CGparameter fp_FogColor;
3957         CGparameter fp_FogHeightFade;
3958         CGparameter fp_FogPlane;
3959         CGparameter fp_FogPlaneViewDist;
3960         CGparameter fp_FogRangeRecip;
3961         CGparameter fp_LightColor;
3962         CGparameter fp_LightDir;
3963         CGparameter fp_LightPosition;
3964         CGparameter fp_OffsetMapping_Scale;
3965         CGparameter fp_PixelSize;
3966         CGparameter fp_ReflectColor;
3967         CGparameter fp_ReflectFactor;
3968         CGparameter fp_ReflectOffset;
3969         CGparameter fp_RefractColor;
3970         CGparameter fp_Saturation;
3971         CGparameter fp_ScreenCenterRefractReflect;
3972         CGparameter fp_ScreenScaleRefractReflect;
3973         CGparameter fp_ScreenToDepth;
3974         CGparameter fp_ShadowMap_Parameters;
3975         CGparameter fp_ShadowMap_TextureScale;
3976         CGparameter fp_SpecularPower;
3977         CGparameter fp_UserVec1;
3978         CGparameter fp_UserVec2;
3979         CGparameter fp_UserVec3;
3980         CGparameter fp_UserVec4;
3981         CGparameter fp_ViewTintColor;
3982         CGparameter fp_ViewToLight;
3983         CGparameter fp_PixelToScreenTexCoord;
3984         CGparameter fp_ModelToReflectCube;
3985 }
3986 r_cg_permutation_t;
3987
3988 /// information about each possible shader permutation
3989 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3990 /// currently selected permutation
3991 r_cg_permutation_t *r_cg_permutation;
3992 /// storage for permutations linked in the hash table
3993 memexpandablearray_t r_cg_permutationarray;
3994
3995 #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));}}
3996
3997 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3998 {
3999         //unsigned int hashdepth = 0;
4000         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4001         r_cg_permutation_t *p;
4002         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4003         {
4004                 if (p->mode == mode && p->permutation == permutation)
4005                 {
4006                         //if (hashdepth > 10)
4007                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4008                         return p;
4009                 }
4010                 //hashdepth++;
4011         }
4012         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4013         p->mode = mode;
4014         p->permutation = permutation;
4015         p->hashnext = r_cg_permutationhash[mode][hashindex];
4016         r_cg_permutationhash[mode][hashindex] = p;
4017         //if (hashdepth > 10)
4018         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4019         return p;
4020 }
4021
4022 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4023 {
4024         char *shaderstring;
4025         if (!filename || !filename[0])
4026                 return NULL;
4027         if (!strcmp(filename, "cg/default.cg"))
4028         {
4029                 if (!cgshaderstring)
4030                 {
4031                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4032                         if (cgshaderstring)
4033                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4034                         else
4035                                 cgshaderstring = (char *)builtincgshaderstring;
4036                 }
4037                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4038                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4039                 return shaderstring;
4040         }
4041         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4042         if (shaderstring)
4043         {
4044                 if (printfromdisknotice)
4045                         Con_DPrintf("from disk %s... ", filename);
4046                 return shaderstring;
4047         }
4048         return shaderstring;
4049 }
4050
4051 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4052 {
4053         // TODO: load or create .fp and .vp shader files
4054 }
4055
4056 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4057 {
4058         int i;
4059         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4060         int vertstrings_count = 0, vertstring_length = 0;
4061         int geomstrings_count = 0, geomstring_length = 0;
4062         int fragstrings_count = 0, fragstring_length = 0;
4063         char *t;
4064         char *vertexstring, *geometrystring, *fragmentstring;
4065         char *vertstring, *geomstring, *fragstring;
4066         const char *vertstrings_list[32+3];
4067         const char *geomstrings_list[32+3];
4068         const char *fragstrings_list[32+3];
4069         char permutationname[256];
4070         char cachename[256];
4071         CGprofile vertexProfile;
4072         CGprofile fragmentProfile;
4073
4074         if (p->compiled)
4075                 return;
4076         p->compiled = true;
4077         p->vprogram = NULL;
4078         p->fprogram = NULL;
4079
4080         permutationname[0] = 0;
4081         cachename[0] = 0;
4082         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4083         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4084         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4085
4086         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4087         strlcat(cachename, "cg/", sizeof(cachename));
4088
4089         // the first pretext is which type of shader to compile as
4090         // (later these will all be bound together as a program object)
4091         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4092         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4093         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4094
4095         // the second pretext is the mode (for example a light source)
4096         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4097         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4098         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4099         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4100         strlcat(cachename, modeinfo->name, sizeof(cachename));
4101
4102         // now add all the permutation pretexts
4103         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4104         {
4105                 if (permutation & (1<<i))
4106                 {
4107                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4108                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4109                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4110                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4111                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4112                 }
4113                 else
4114                 {
4115                         // keep line numbers correct
4116                         vertstrings_list[vertstrings_count++] = "\n";
4117                         geomstrings_list[geomstrings_count++] = "\n";
4118                         fragstrings_list[fragstrings_count++] = "\n";
4119                 }
4120         }
4121
4122         // replace spaces in the cachename with _ characters
4123         for (i = 0;cachename[i];i++)
4124                 if (cachename[i] == ' ')
4125                         cachename[i] = '_';
4126
4127         // now append the shader text itself
4128         vertstrings_list[vertstrings_count++] = vertexstring;
4129         geomstrings_list[geomstrings_count++] = geometrystring;
4130         fragstrings_list[fragstrings_count++] = fragmentstring;
4131
4132         // if any sources were NULL, clear the respective list
4133         if (!vertexstring)
4134                 vertstrings_count = 0;
4135         if (!geometrystring)
4136                 geomstrings_count = 0;
4137         if (!fragmentstring)
4138                 fragstrings_count = 0;
4139
4140         vertstring_length = 0;
4141         for (i = 0;i < vertstrings_count;i++)
4142                 vertstring_length += strlen(vertstrings_list[i]);
4143         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4144         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4145                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4146
4147         geomstring_length = 0;
4148         for (i = 0;i < geomstrings_count;i++)
4149                 geomstring_length += strlen(geomstrings_list[i]);
4150         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4151         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4152                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4153
4154         fragstring_length = 0;
4155         for (i = 0;i < fragstrings_count;i++)
4156                 fragstring_length += strlen(fragstrings_list[i]);
4157         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4158         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4159                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4160
4161         CHECKGLERROR
4162         CHECKCGERROR
4163         //vertexProfile = CG_PROFILE_ARBVP1;
4164         //fragmentProfile = CG_PROFILE_ARBFP1;
4165         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4166         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4167         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4168         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4169         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4170         CHECKGLERROR
4171
4172         // try to load the cached shader, or generate one
4173         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4174
4175         // if caching failed, do a dynamic compile for now
4176         CHECKCGERROR
4177         if (vertstring[0] && !p->vprogram)
4178                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4179         CHECKCGERROR
4180         if (fragstring[0] && !p->fprogram)
4181                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4182         CHECKCGERROR
4183
4184         // look up all the uniform variable names we care about, so we don't
4185         // have to look them up every time we set them
4186         if (p->vprogram)
4187         {
4188                 CHECKCGERROR
4189                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4190                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4191                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4192                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4193                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4194                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4195                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4196                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4197                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4198                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4199                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4200                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4201                 CHECKCGERROR
4202         }
4203         if (p->fprogram)
4204         {
4205                 CHECKCGERROR
4206                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4207                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4208                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4209                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4210                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4211                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4212                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4213                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4214                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4215                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4216                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4217                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4218                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4219                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4220                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4221                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4222                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4223                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4224                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4225                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4226                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4227                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4228                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4229                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4230                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4231                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4232                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4233                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4234                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4235                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4236                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4237                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4238                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4239                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4240                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4241                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4242                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4243                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4244                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4245                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4246                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4247                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4248                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4249                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4250                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4251                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4252                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4253                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4254                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4255                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4256                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4257                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4258                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4259                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4260                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4261                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4262                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4263                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4264                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4265                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4266                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4267                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4268                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4269                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4270                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4271                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4272                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4273                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4274                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4275                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4276                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4277                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4278                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4279                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4280                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4281                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4282                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4283                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4284                 CHECKCGERROR
4285         }
4286
4287         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4288                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4289         else
4290                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4291
4292         // free the strings
4293         if (vertstring)
4294                 Mem_Free(vertstring);
4295         if (geomstring)
4296                 Mem_Free(geomstring);
4297         if (fragstring)
4298                 Mem_Free(fragstring);
4299         if (vertexstring)
4300                 Mem_Free(vertexstring);
4301         if (geometrystring)
4302                 Mem_Free(geometrystring);
4303         if (fragmentstring)
4304                 Mem_Free(fragmentstring);
4305 }
4306
4307 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4308 {
4309         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4310         CHECKGLERROR
4311         CHECKCGERROR
4312         if (r_cg_permutation != perm)
4313         {
4314                 r_cg_permutation = perm;
4315                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4316                 {
4317                         if (!r_cg_permutation->compiled)
4318                                 R_CG_CompilePermutation(perm, mode, permutation);
4319                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4320                         {
4321                                 // remove features until we find a valid permutation
4322                                 int i;
4323                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4324                                 {
4325                                         // reduce i more quickly whenever it would not remove any bits
4326                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4327                                         if (!(permutation & j))
4328                                                 continue;
4329                                         permutation -= j;
4330                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4331                                         if (!r_cg_permutation->compiled)
4332                                                 R_CG_CompilePermutation(perm, mode, permutation);
4333                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4334                                                 break;
4335                                 }
4336                                 if (i >= SHADERPERMUTATION_COUNT)
4337                                 {
4338                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4339                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4340                                         return; // no bit left to clear, entire mode is broken
4341                                 }
4342                         }
4343                 }
4344                 CHECKGLERROR
4345                 CHECKCGERROR
4346                 if (r_cg_permutation->vprogram)
4347                 {
4348                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4349                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4350                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4351                 }
4352                 else
4353                 {
4354                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4355                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4356                 }
4357                 if (r_cg_permutation->fprogram)
4358                 {
4359                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4360                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4361                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4362                 }
4363                 else
4364                 {
4365                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4366                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4367                 }
4368         }
4369         CHECKCGERROR
4370         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4371         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4372         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4373 }
4374
4375 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4376 {
4377         cgGLSetTextureParameter(param, R_GetTexture(tex));
4378         cgGLEnableTextureParameter(param);
4379 }
4380 #endif
4381
4382 void R_GLSL_Restart_f(void)
4383 {
4384         unsigned int i, limit;
4385         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4386                 Mem_Free(glslshaderstring);
4387         glslshaderstring = NULL;
4388         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4389                 Mem_Free(cgshaderstring);
4390         cgshaderstring = NULL;
4391         switch(vid.renderpath)
4392         {
4393         case RENDERPATH_GL20:
4394                 {
4395                         r_glsl_permutation_t *p;
4396                         r_glsl_permutation = NULL;
4397                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4398                         for (i = 0;i < limit;i++)
4399                         {
4400                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4401                                 {
4402                                         GL_Backend_FreeProgram(p->program);
4403                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4404                                 }
4405                         }
4406                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4407                 }
4408                 break;
4409         case RENDERPATH_CGGL:
4410 #ifdef SUPPORTCG
4411                 {
4412                         r_cg_permutation_t *p;
4413                         r_cg_permutation = NULL;
4414                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4415                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4416                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4417                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4418                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4419                         for (i = 0;i < limit;i++)
4420                         {
4421                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4422                                 {
4423                                         if (p->vprogram)
4424                                                 cgDestroyProgram(p->vprogram);
4425                                         if (p->fprogram)
4426                                                 cgDestroyProgram(p->fprogram);
4427                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4428                                 }
4429                         }
4430                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4431                 }
4432                 break;
4433 #endif
4434         case RENDERPATH_GL13:
4435         case RENDERPATH_GL11:
4436                 break;
4437         }
4438 }
4439
4440 void R_GLSL_DumpShader_f(void)
4441 {
4442         int i;
4443         qfile_t *file;
4444
4445         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4446         if (file)
4447         {
4448                 FS_Print(file, "/* The engine may define the following macros:\n");
4449                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4450                 for (i = 0;i < SHADERMODE_COUNT;i++)
4451                         FS_Print(file, glslshadermodeinfo[i].pretext);
4452                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4453                         FS_Print(file, shaderpermutationinfo[i].pretext);
4454                 FS_Print(file, "*/\n");
4455                 FS_Print(file, builtinshaderstring);
4456                 FS_Close(file);
4457                 Con_Printf("glsl/default.glsl written\n");
4458         }
4459         else
4460                 Con_Printf("failed to write to glsl/default.glsl\n");
4461
4462 #ifdef SUPPORTCG
4463         file = FS_OpenRealFile("cg/default.cg", "w", false);
4464         if (file)
4465         {
4466                 FS_Print(file, "/* The engine may define the following macros:\n");
4467                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4468                 for (i = 0;i < SHADERMODE_COUNT;i++)
4469                         FS_Print(file, cgshadermodeinfo[i].pretext);
4470                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4471                         FS_Print(file, shaderpermutationinfo[i].pretext);
4472                 FS_Print(file, "*/\n");
4473                 FS_Print(file, builtincgshaderstring);
4474                 FS_Close(file);
4475                 Con_Printf("cg/default.cg written\n");
4476         }
4477         else
4478                 Con_Printf("failed to write to cg/default.cg\n");
4479 #endif
4480 }
4481
4482 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4483 {
4484         if (!second)
4485                 texturemode = GL_MODULATE;
4486         switch (vid.renderpath)
4487         {
4488         case RENDERPATH_GL20:
4489                 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))));
4490                 if (r_glsl_permutation->loc_Texture_First ) R_Mesh_TexBind(GL20TU_FIRST , first );
4491                 if (r_glsl_permutation->loc_Texture_Second) R_Mesh_TexBind(GL20TU_SECOND, second);
4492                 break;
4493         case RENDERPATH_CGGL:
4494 #ifdef SUPPORTCG
4495                 CHECKCGERROR
4496                 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))));
4497                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4498                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4499 #endif
4500                 break;
4501         case RENDERPATH_GL13:
4502                 R_Mesh_TexBind(0, first );
4503                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4504                 R_Mesh_TexBind(1, second);
4505                 if (second)
4506                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4507                 break;
4508         case RENDERPATH_GL11:
4509                 R_Mesh_TexBind(0, first );
4510                 break;
4511         }
4512 }
4513
4514 void R_SetupShader_DepthOrShadow(void)
4515 {
4516         switch (vid.renderpath)
4517         {
4518         case RENDERPATH_GL20:
4519                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4520                 break;
4521         case RENDERPATH_CGGL:
4522 #ifdef SUPPORTCG
4523                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
4524 #endif
4525                 break;
4526         case RENDERPATH_GL13:
4527                 R_Mesh_TexBind(0, 0);
4528                 R_Mesh_TexBind(1, 0);
4529                 break;
4530         case RENDERPATH_GL11:
4531                 R_Mesh_TexBind(0, 0);
4532                 break;
4533         }
4534 }
4535
4536 void R_SetupShader_ShowDepth(void)
4537 {
4538         switch (vid.renderpath)
4539         {
4540         case RENDERPATH_GL20:
4541                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4542                 break;
4543         case RENDERPATH_CGGL:
4544 #ifdef SUPPORTCG
4545                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
4546 #endif
4547                 break;
4548         case RENDERPATH_GL13:
4549                 break;
4550         case RENDERPATH_GL11:
4551                 break;
4552         }
4553 }
4554
4555 extern qboolean r_shadow_usingdeferredprepass;
4556 extern cvar_t r_shadow_deferred_8bitrange;
4557 extern rtexture_t *r_shadow_attenuationgradienttexture;
4558 extern rtexture_t *r_shadow_attenuation2dtexture;
4559 extern rtexture_t *r_shadow_attenuation3dtexture;
4560 extern qboolean r_shadow_usingshadowmaprect;
4561 extern qboolean r_shadow_usingshadowmapcube;
4562 extern qboolean r_shadow_usingshadowmap2d;
4563 extern qboolean r_shadow_usingshadowmaportho;
4564 extern float r_shadow_shadowmap_texturescale[2];
4565 extern float r_shadow_shadowmap_parameters[4];
4566 extern qboolean r_shadow_shadowmapvsdct;
4567 extern qboolean r_shadow_shadowmapsampler;
4568 extern int r_shadow_shadowmappcf;
4569 extern rtexture_t *r_shadow_shadowmaprectangletexture;
4570 extern rtexture_t *r_shadow_shadowmap2dtexture;
4571 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
4572 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4573 extern matrix4x4_t r_shadow_shadowmapmatrix;
4574 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4575 extern int r_shadow_prepass_width;
4576 extern int r_shadow_prepass_height;
4577 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4578 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4579 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4580 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4581 extern cvar_t gl_mesh_separatearrays;
4582 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)
4583 {
4584         // select a permutation of the lighting shader appropriate to this
4585         // combination of texture, entity, light source, and fogging, only use the
4586         // minimum features necessary to avoid wasting rendering time in the
4587         // fragment shader on features that are not being used
4588         unsigned int permutation = 0;
4589         unsigned int mode = 0;
4590         float m16f[16];
4591         if (rsurfacepass == RSURFPASS_BACKGROUND)
4592         {
4593                 // distorted background
4594                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4595                         mode = SHADERMODE_WATER;
4596                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4597                         mode = SHADERMODE_REFRACTION;
4598                 else
4599                 {
4600                         mode = SHADERMODE_GENERIC;
4601                         permutation |= SHADERPERMUTATION_DIFFUSE;
4602                 }
4603                 GL_AlphaTest(false);
4604                 GL_BlendFunc(GL_ONE, GL_ZERO);
4605         }
4606         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4607         {
4608                 if (r_glsl_offsetmapping.integer)
4609                 {
4610                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4611                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4612                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4613                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4614                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4615                         {
4616                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4617                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4618                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4619                         }
4620                 }
4621                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4622                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4623                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4624                         permutation |= SHADERPERMUTATION_ALPHAKILL;
4625                 // normalmap (deferred prepass), may use alpha test on diffuse
4626                 mode = SHADERMODE_DEFERREDGEOMETRY;
4627                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4628                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4629                 GL_AlphaTest(false);
4630                 GL_BlendFunc(GL_ONE, GL_ZERO);
4631         }
4632         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4633         {
4634                 if (r_glsl_offsetmapping.integer)
4635                 {
4636                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4637                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4638                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4639                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4640                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4641                         {
4642                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4643                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4644                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4645                         }
4646                 }
4647                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4648                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4649                 // light source
4650                 mode = SHADERMODE_LIGHTSOURCE;
4651                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4652                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4653                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4654                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4655                 if (diffusescale > 0)
4656                         permutation |= SHADERPERMUTATION_DIFFUSE;
4657                 if (specularscale > 0)
4658                 {
4659                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4660                         if (r_shadow_glossexact.integer)
4661                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4662                 }
4663                 if (r_refdef.fogenabled)
4664                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4665                 if (rsurface.texture->colormapping)
4666                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4667                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
4668                 {
4669                         if (r_shadow_usingshadowmaprect)
4670                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4671                         if (r_shadow_usingshadowmap2d)
4672                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4673                         if (r_shadow_usingshadowmapcube)
4674                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
4675                         else if(r_shadow_shadowmapvsdct)
4676                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4677
4678                         if (r_shadow_shadowmapsampler)
4679                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4680                         if (r_shadow_shadowmappcf > 1)
4681                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4682                         else if (r_shadow_shadowmappcf)
4683                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4684                 }
4685                 if (rsurface.texture->reflectmasktexture)
4686                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4687                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4688                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4689         }
4690         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4691         {
4692                 if (r_glsl_offsetmapping.integer)
4693                 {
4694                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4695                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4696                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4697                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4698                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4699                         {
4700                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4701                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4702                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4703                         }
4704                 }
4705                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4706                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4707                 // unshaded geometry (fullbright or ambient model lighting)
4708                 mode = SHADERMODE_FLATCOLOR;
4709                 ambientscale = diffusescale = specularscale = 0;
4710                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4711                         permutation |= SHADERPERMUTATION_GLOW;
4712                 if (r_refdef.fogenabled)
4713                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4714                 if (rsurface.texture->colormapping)
4715                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4716                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4717                 {
4718                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4719                         if (r_shadow_usingshadowmaprect)
4720                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4721                         if (r_shadow_usingshadowmap2d)
4722                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4723
4724                         if (r_shadow_shadowmapsampler)
4725                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4726                         if (r_shadow_shadowmappcf > 1)
4727                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4728                         else if (r_shadow_shadowmappcf)
4729                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4730                 }
4731                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4732                         permutation |= SHADERPERMUTATION_REFLECTION;
4733                 if (rsurface.texture->reflectmasktexture)
4734                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4735                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4736                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4737         }
4738         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
4739         {
4740                 if (r_glsl_offsetmapping.integer)
4741                 {
4742                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4743                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4744                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4745                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4746                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4747                         {
4748                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4749                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4750                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4751                         }
4752                 }
4753                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4754                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4755                 // directional model lighting
4756                 mode = SHADERMODE_LIGHTDIRECTION;
4757                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4758                         permutation |= SHADERPERMUTATION_GLOW;
4759                 permutation |= SHADERPERMUTATION_DIFFUSE;
4760                 if (specularscale > 0)
4761                 {
4762                         permutation |= SHADERPERMUTATION_SPECULAR;
4763                         if (r_shadow_glossexact.integer)
4764                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4765                 }
4766                 if (r_refdef.fogenabled)
4767                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4768                 if (rsurface.texture->colormapping)
4769                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4770                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4771                 {
4772                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4773                         if (r_shadow_usingshadowmaprect)
4774                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4775                         if (r_shadow_usingshadowmap2d)
4776                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4777
4778                         if (r_shadow_shadowmapsampler)
4779                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4780                         if (r_shadow_shadowmappcf > 1)
4781                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4782                         else if (r_shadow_shadowmappcf)
4783                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4784                 }
4785                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4786                         permutation |= SHADERPERMUTATION_REFLECTION;
4787                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4788                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4789                 if (rsurface.texture->reflectmasktexture)
4790                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4791                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4792                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4793         }
4794         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
4795         {
4796                 if (r_glsl_offsetmapping.integer)
4797                 {
4798                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4799                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4800                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4801                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4802                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4803                         {
4804                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4805                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4806                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4807                         }
4808                 }
4809                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4810                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4811                 // ambient model lighting
4812                 mode = SHADERMODE_LIGHTDIRECTION;
4813                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4814                         permutation |= SHADERPERMUTATION_GLOW;
4815                 if (r_refdef.fogenabled)
4816                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4817                 if (rsurface.texture->colormapping)
4818                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4819                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4820                 {
4821                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4822                         if (r_shadow_usingshadowmaprect)
4823                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4824                         if (r_shadow_usingshadowmap2d)
4825                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4826
4827                         if (r_shadow_shadowmapsampler)
4828                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4829                         if (r_shadow_shadowmappcf > 1)
4830                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4831                         else if (r_shadow_shadowmappcf)
4832                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4833                 }
4834                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4835                         permutation |= SHADERPERMUTATION_REFLECTION;
4836                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4837                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4838                 if (rsurface.texture->reflectmasktexture)
4839                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4840                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4841                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4842         }
4843         else
4844         {
4845                 if (r_glsl_offsetmapping.integer)
4846                 {
4847                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4848                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4849                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4850                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4851                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4852                         {
4853                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4854                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4855                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4856                         }
4857                 }
4858                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4859                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4860                 // lightmapped wall
4861                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4862                         permutation |= SHADERPERMUTATION_GLOW;
4863                 if (r_refdef.fogenabled)
4864                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4865                 if (rsurface.texture->colormapping)
4866                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4867                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4868                 {
4869                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4870                         if (r_shadow_usingshadowmaprect)
4871                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
4872                         if (r_shadow_usingshadowmap2d)
4873                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4874
4875                         if (r_shadow_shadowmapsampler)
4876                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4877                         if (r_shadow_shadowmappcf > 1)
4878                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4879                         else if (r_shadow_shadowmappcf)
4880                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4881                 }
4882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
4883                         permutation |= SHADERPERMUTATION_REFLECTION;
4884                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
4885                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
4886                 if (rsurface.texture->reflectmasktexture)
4887                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4888                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
4889                 {
4890                         // deluxemapping (light direction texture)
4891                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
4892                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
4893                         else
4894                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4895                         permutation |= SHADERPERMUTATION_DIFFUSE;
4896                         if (specularscale > 0)
4897                         {
4898                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4899                                 if (r_shadow_glossexact.integer)
4900                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4901                         }
4902                 }
4903                 else if (r_glsl_deluxemapping.integer >= 2)
4904                 {
4905                         // fake deluxemapping (uniform light direction in tangentspace)
4906                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
4907                         permutation |= SHADERPERMUTATION_DIFFUSE;
4908                         if (specularscale > 0)
4909                         {
4910                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4911                                 if (r_shadow_glossexact.integer)
4912                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
4913                         }
4914                 }
4915                 else if (rsurface.uselightmaptexture)
4916                 {
4917                         // ordinary lightmapping (q1bsp, q3bsp)
4918                         mode = SHADERMODE_LIGHTMAP;
4919                 }
4920                 else
4921                 {
4922                         // ordinary vertex coloring (q3bsp)
4923                         mode = SHADERMODE_VERTEXCOLOR;
4924                 }
4925                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
4926                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
4927         }
4928         switch(vid.renderpath)
4929         {
4930         case RENDERPATH_GL20:
4931                 if (gl_mesh_separatearrays.integer)
4932                 {
4933                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4934                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
4935                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
4936                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
4937                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
4938                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
4939                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
4940                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
4941                 }
4942                 else
4943                 {
4944                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
4945                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
4946                 }
4947                 R_SetupShader_SetPermutationGLSL(mode, permutation);
4948                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
4949                 if (mode == SHADERMODE_LIGHTSOURCE)
4950                 {
4951                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
4952                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
4953                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
4954                         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);
4955                         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);
4956                         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);
4957         
4958                         // additive passes are only darkened by fog, not tinted
4959                         if (r_glsl_permutation->loc_FogColor >= 0)
4960                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4961                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
4962                 }
4963                 else
4964                 {
4965                         if (mode == SHADERMODE_FLATCOLOR)
4966                         {
4967                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);
4968                         }
4969                         else if (mode == SHADERMODE_LIGHTDIRECTION)
4970                         {
4971                                 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]);
4972                                 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]);
4973                                 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);
4974                                 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);
4975                                 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);
4976                                 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]);
4977                                 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]);
4978                         }
4979                         else
4980                         {
4981                                 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]);
4982                                 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]);
4983                                 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);
4984                                 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);
4985                                 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);
4986                         }
4987                         // additive passes are only darkened by fog, not tinted
4988                         if (r_glsl_permutation->loc_FogColor >= 0)
4989                         {
4990                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
4991                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
4992                                 else
4993                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
4994                         }
4995                         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);
4996                         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]);
4997                         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]);
4998                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
4999                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5000                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5001                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5002                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5003                 }
5004                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5005                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5006                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5007                 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]);
5008                 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]);
5009
5010                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5011                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5012                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5013                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5014                 {
5015                         if (rsurface.texture->pantstexture)
5016                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5017                         else
5018                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5019                 }
5020                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5021                 {
5022                         if (rsurface.texture->shirttexture)
5023                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5024                         else
5025                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5026                 }
5027                 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]);
5028                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5029                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5030                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5031                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5032                 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]);
5033                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5034
5035         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5036         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5037         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5038                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5039                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5040                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5041                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5042                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5043                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5044                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5045                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5046                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5047                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5048                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5049                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5050                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5051                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5052                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , r_texture_white                                     );
5053                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , r_texture_blanknormalmap                            );
5054                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5055                 if (r_glsl_permutation->loc_Texture_Refraction      >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , r_texture_white                                     );
5056                 if (r_glsl_permutation->loc_Texture_Reflection      >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , r_texture_white                                     );
5057                 if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5058                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5059                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5060                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5061                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5062                 {
5063                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5064                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
5065                         if (rsurface.rtlight)
5066                         {
5067                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5068                                 if (r_shadow_usingshadowmapcube)
5069                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5070                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5071                         }
5072                 }
5073                 CHECKGLERROR
5074                 break;
5075         case RENDERPATH_CGGL:
5076 #ifdef SUPPORTCG
5077                 if (gl_mesh_separatearrays.integer)
5078                 {
5079                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5080                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5081                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5082                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5083                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5084                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5085                         R_Mesh_TexCoordPointer(3, 4, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5086                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5087                 }
5088                 else
5089                 {
5090                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
5091                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5092                 }
5093                 R_SetupShader_SetPermutationCG(mode, permutation);
5094                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5095                 if (mode == SHADERMODE_LIGHTSOURCE)
5096                 {
5097                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5098                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5099                 }
5100                 else
5101                 {
5102                         if (mode == SHADERMODE_LIGHTDIRECTION)
5103                         {
5104                                 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
5105                         }
5106                 }
5107                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5108                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5109                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5110                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5111                 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
5112                 CHECKGLERROR
5113
5114                 if (mode == SHADERMODE_LIGHTSOURCE)
5115                 {
5116                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5117                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5118                         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
5119                         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
5120                         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
5121
5122                         // additive passes are only darkened by fog, not tinted
5123                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5124                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5125                 }
5126                 else
5127                 {
5128                         if (mode == SHADERMODE_FLATCOLOR)
5129                         {
5130                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2]);CHECKCGERROR
5131                         }
5132                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5133                         {
5134                                 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
5135                                 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
5136                                 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
5137                                 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
5138                                 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
5139                                 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
5140                                 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
5141                         }
5142                         else
5143                         {
5144                                 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
5145                                 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
5146                                 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
5147                                 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
5148                                 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
5149                         }
5150                         // additive passes are only darkened by fog, not tinted
5151                         if (r_cg_permutation->fp_FogColor)
5152                         {
5153                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5154                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5155                                 else
5156                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5157                                 CHECKCGERROR
5158                         }
5159                         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
5160                         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
5161                         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
5162                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5163                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5164                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5165                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5166                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5167                 }
5168                 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
5169                 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
5170                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5171                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5172                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5173                 if (r_cg_permutation->fp_Color_Pants)
5174                 {
5175                         if (rsurface.texture->pantstexture)
5176                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5177                         else
5178                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5179                         CHECKCGERROR
5180                 }
5181                 if (r_cg_permutation->fp_Color_Shirt)
5182                 {
5183                         if (rsurface.texture->shirttexture)
5184                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5185                         else
5186                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5187                         CHECKCGERROR
5188                 }
5189                 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
5190                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5191                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5192                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5193                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5194                 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
5195                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5196
5197         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5198         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5199         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5200                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5201                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5202                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5203                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5204                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5205                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5206                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5207                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5208                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5209                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5210                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5211                 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
5212                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5213                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5214                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , r_texture_white                                     );CHECKCGERROR
5215                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , r_texture_blanknormalmap                            );CHECKCGERROR
5216                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5217                 if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , r_texture_white                                     );CHECKCGERROR
5218                 if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , r_texture_white                                     );CHECKCGERROR
5219                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5220                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5221                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5222                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5223                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5224                 {
5225                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5226                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5227                         if (rsurface.rtlight)
5228                         {
5229                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5230                                 if (r_shadow_usingshadowmapcube)
5231                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5232                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5233                         }
5234                 }
5235
5236                 CHECKGLERROR
5237 #endif
5238                 break;
5239         case RENDERPATH_GL13:
5240         case RENDERPATH_GL11:
5241                 break;
5242         }
5243 }
5244
5245 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5246 {
5247         // select a permutation of the lighting shader appropriate to this
5248         // combination of texture, entity, light source, and fogging, only use the
5249         // minimum features necessary to avoid wasting rendering time in the
5250         // fragment shader on features that are not being used
5251         unsigned int permutation = 0;
5252         unsigned int mode = 0;
5253         const float *lightcolorbase = rtlight->currentcolor;
5254         float ambientscale = rtlight->ambientscale;
5255         float diffusescale = rtlight->diffusescale;
5256         float specularscale = rtlight->specularscale;
5257         // this is the location of the light in view space
5258         vec3_t viewlightorigin;
5259         // this transforms from view space (camera) to light space (cubemap)
5260         matrix4x4_t viewtolight;
5261         matrix4x4_t lighttoview;
5262         float viewtolight16f[16];
5263         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5264         // light source
5265         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5266         if (rtlight->currentcubemap != r_texture_whitecube)
5267                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5268         if (diffusescale > 0)
5269                 permutation |= SHADERPERMUTATION_DIFFUSE;
5270         if (specularscale > 0)
5271         {
5272                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5273                 if (r_shadow_glossexact.integer)
5274                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5275         }
5276         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5277         {
5278                 if (r_shadow_usingshadowmaprect)
5279                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5280                 if (r_shadow_usingshadowmap2d)
5281                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5282                 if (r_shadow_usingshadowmapcube)
5283                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5284                 else if(r_shadow_shadowmapvsdct)
5285                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5286
5287                 if (r_shadow_shadowmapsampler)
5288                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5289                 if (r_shadow_shadowmappcf > 1)
5290                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5291                 else if (r_shadow_shadowmappcf)
5292                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5293         }
5294         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5295         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5296         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5297         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5298         switch(vid.renderpath)
5299         {
5300         case RENDERPATH_GL20:
5301                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5302                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5303                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5304                 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);
5305                 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);
5306                 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);
5307                 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]);
5308                 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]);
5309                 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));
5310                 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]);
5311                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5312
5313                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5314                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5315                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5316                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5317                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
5318                 if (r_shadow_usingshadowmapcube)
5319                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
5320                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5321                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5322                 break;
5323         case RENDERPATH_CGGL:
5324 #ifdef SUPPORTCG
5325                 R_SetupShader_SetPermutationCG(mode, permutation);
5326                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
5327                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
5328                 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
5329                 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
5330                 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
5331                 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
5332                 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
5333                 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
5334                 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
5335                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5336
5337                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5338                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5339                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5340                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5341                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
5342                 if (r_shadow_usingshadowmapcube)
5343                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
5344                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5345                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5346 #endif
5347                 break;
5348         case RENDERPATH_GL13:
5349         case RENDERPATH_GL11:
5350                 break;
5351         }
5352 }
5353
5354 #define SKINFRAME_HASH 1024
5355
5356 typedef struct
5357 {
5358         int loadsequence; // incremented each level change
5359         memexpandablearray_t array;
5360         skinframe_t *hash[SKINFRAME_HASH];
5361 }
5362 r_skinframe_t;
5363 r_skinframe_t r_skinframe;
5364
5365 void R_SkinFrame_PrepareForPurge(void)
5366 {
5367         r_skinframe.loadsequence++;
5368         // wrap it without hitting zero
5369         if (r_skinframe.loadsequence >= 200)
5370                 r_skinframe.loadsequence = 1;
5371 }
5372
5373 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5374 {
5375         if (!skinframe)
5376                 return;
5377         // mark the skinframe as used for the purging code
5378         skinframe->loadsequence = r_skinframe.loadsequence;
5379 }
5380
5381 void R_SkinFrame_Purge(void)
5382 {
5383         int i;
5384         skinframe_t *s;
5385         for (i = 0;i < SKINFRAME_HASH;i++)
5386         {
5387                 for (s = r_skinframe.hash[i];s;s = s->next)
5388                 {
5389                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5390                         {
5391                                 if (s->merged == s->base)
5392                                         s->merged = NULL;
5393                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5394                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5395                                 R_PurgeTexture(s->merged);s->merged = NULL;
5396                                 R_PurgeTexture(s->base  );s->base   = NULL;
5397                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5398                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5399                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5400                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5401                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5402                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5403                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5404                                 s->loadsequence = 0;
5405                         }
5406                 }
5407         }
5408 }
5409
5410 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5411         skinframe_t *item;
5412         char basename[MAX_QPATH];
5413
5414         Image_StripImageExtension(name, basename, sizeof(basename));
5415
5416         if( last == NULL ) {
5417                 int hashindex;
5418                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5419                 item = r_skinframe.hash[hashindex];
5420         } else {
5421                 item = last->next;
5422         }
5423
5424         // linearly search through the hash bucket
5425         for( ; item ; item = item->next ) {
5426                 if( !strcmp( item->basename, basename ) ) {
5427                         return item;
5428                 }
5429         }
5430         return NULL;
5431 }
5432
5433 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5434 {
5435         skinframe_t *item;
5436         int hashindex;
5437         char basename[MAX_QPATH];
5438
5439         Image_StripImageExtension(name, basename, sizeof(basename));
5440
5441         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5442         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5443                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5444                         break;
5445
5446         if (!item) {
5447                 rtexture_t *dyntexture;
5448                 // check whether its a dynamic texture
5449                 dyntexture = CL_GetDynTexture( basename );
5450                 if (!add && !dyntexture)
5451                         return NULL;
5452                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5453                 memset(item, 0, sizeof(*item));
5454                 strlcpy(item->basename, basename, sizeof(item->basename));
5455                 item->base = dyntexture; // either NULL or dyntexture handle
5456                 item->textureflags = textureflags;
5457                 item->comparewidth = comparewidth;
5458                 item->compareheight = compareheight;
5459                 item->comparecrc = comparecrc;
5460                 item->next = r_skinframe.hash[hashindex];
5461                 r_skinframe.hash[hashindex] = item;
5462         }
5463         else if( item->base == NULL )
5464         {
5465                 rtexture_t *dyntexture;
5466                 // check whether its a dynamic texture
5467                 // 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]
5468                 dyntexture = CL_GetDynTexture( basename );
5469                 item->base = dyntexture; // either NULL or dyntexture handle
5470         }
5471
5472         R_SkinFrame_MarkUsed(item);
5473         return item;
5474 }
5475
5476 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5477         { \
5478                 unsigned long long avgcolor[5], wsum; \
5479                 int pix, comp, w; \
5480                 avgcolor[0] = 0; \
5481                 avgcolor[1] = 0; \
5482                 avgcolor[2] = 0; \
5483                 avgcolor[3] = 0; \
5484                 avgcolor[4] = 0; \
5485                 wsum = 0; \
5486                 for(pix = 0; pix < cnt; ++pix) \
5487                 { \
5488                         w = 0; \
5489                         for(comp = 0; comp < 3; ++comp) \
5490                                 w += getpixel; \
5491                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5492                         { \
5493                                 ++wsum; \
5494                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5495                                 w = getpixel; \
5496                                 for(comp = 0; comp < 3; ++comp) \
5497                                         avgcolor[comp] += getpixel * w; \
5498                                 avgcolor[3] += w; \
5499                         } \
5500                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5501                         avgcolor[4] += getpixel; \
5502                 } \
5503                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5504                         avgcolor[3] = 1; \
5505                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5506                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5507                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5508                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5509         }
5510
5511 extern cvar_t gl_picmip;
5512 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5513 {
5514         int j;
5515         unsigned char *pixels;
5516         unsigned char *bumppixels;
5517         unsigned char *basepixels = NULL;
5518         int basepixels_width = 0;
5519         int basepixels_height = 0;
5520         skinframe_t *skinframe;
5521         rtexture_t *ddsbase = NULL;
5522         qboolean ddshasalpha = false;
5523         float ddsavgcolor[4];
5524         char basename[MAX_QPATH];
5525         int miplevel = R_PicmipForFlags(textureflags);
5526         int savemiplevel = miplevel;
5527         int mymiplevel;
5528
5529         if (cls.state == ca_dedicated)
5530                 return NULL;
5531
5532         // return an existing skinframe if already loaded
5533         // if loading of the first image fails, don't make a new skinframe as it
5534         // would cause all future lookups of this to be missing
5535         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5536         if (skinframe && skinframe->base)
5537                 return skinframe;
5538
5539         Image_StripImageExtension(name, basename, sizeof(basename));
5540
5541         // check for DDS texture file first
5542         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5543         {
5544                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer, &miplevel);
5545                 if (basepixels == NULL)
5546                         return NULL;
5547         }
5548
5549         // FIXME handle miplevel
5550
5551         if (developer_loading.integer)
5552                 Con_Printf("loading skin \"%s\"\n", name);
5553
5554         // we've got some pixels to store, so really allocate this new texture now
5555         if (!skinframe)
5556                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5557         skinframe->stain = NULL;
5558         skinframe->merged = NULL;
5559         skinframe->base = NULL;
5560         skinframe->pants = NULL;
5561         skinframe->shirt = NULL;
5562         skinframe->nmap = NULL;
5563         skinframe->gloss = NULL;
5564         skinframe->glow = NULL;
5565         skinframe->fog = NULL;
5566         skinframe->reflect = NULL;
5567         skinframe->hasalpha = false;
5568
5569         if (ddsbase)
5570         {
5571                 skinframe->base = ddsbase;
5572                 skinframe->hasalpha = ddshasalpha;
5573                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5574                 if (r_loadfog && skinframe->hasalpha)
5575                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5576                 //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]);
5577         }
5578         else
5579         {
5580                 basepixels_width = image_width;
5581                 basepixels_height = image_height;
5582                 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), miplevel, NULL);
5583                 if (textureflags & TEXF_ALPHA)
5584                 {
5585                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5586                         {
5587                                 if (basepixels[j] < 255)
5588                                 {
5589                                         skinframe->hasalpha = true;
5590                                         break;
5591                                 }
5592                         }
5593                         if (r_loadfog && skinframe->hasalpha)
5594                         {
5595                                 // has transparent pixels
5596                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5597                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5598                                 {
5599                                         pixels[j+0] = 255;
5600                                         pixels[j+1] = 255;
5601                                         pixels[j+2] = 255;
5602                                         pixels[j+3] = basepixels[j+3];
5603                                 }
5604                                 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), miplevel, NULL);
5605                                 Mem_Free(pixels);
5606                         }
5607                 }
5608                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
5609                 //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]);
5610                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
5611                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true);
5612                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
5613                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true);
5614         }
5615
5616         if (r_loaddds)
5617         {
5618                 mymiplevel = savemiplevel;
5619                 if (r_loadnormalmap)
5620                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, mymiplevel);
5621                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5622                 if (r_loadgloss)
5623                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5624                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5625                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5626                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
5627         }
5628
5629         // _norm is the name used by tenebrae and has been adopted as standard
5630         if (r_loadnormalmap && skinframe->nmap == NULL)
5631         {
5632                 mymiplevel = savemiplevel;
5633                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5634                 {
5635                         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), mymiplevel, NULL);
5636                         Mem_Free(pixels);
5637                         pixels = NULL;
5638                 }
5639                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
5640                 {
5641                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5642                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
5643                         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), mymiplevel, NULL);
5644                         Mem_Free(pixels);
5645                         Mem_Free(bumppixels);
5646                 }
5647                 else if (r_shadow_bumpscale_basetexture.value > 0)
5648                 {
5649                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
5650                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
5651                         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), mymiplevel, NULL);
5652                         Mem_Free(pixels);
5653                 }
5654                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
5655                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true);
5656         }
5657
5658         // _luma is supported only for tenebrae compatibility
5659         // _glow is the preferred name
5660         mymiplevel = savemiplevel;
5661         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel))))
5662         {
5663                 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), mymiplevel, NULL);
5664                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
5665                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true);
5666                 Mem_Free(pixels);pixels = NULL;
5667         }
5668
5669         mymiplevel = savemiplevel;
5670         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5671         {
5672                 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), mymiplevel, NULL);
5673                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
5674                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true);
5675                 Mem_Free(pixels);
5676                 pixels = NULL;
5677         }
5678
5679         mymiplevel = savemiplevel;
5680         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5681         {
5682                 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), mymiplevel, NULL);
5683                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
5684                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true);
5685                 Mem_Free(pixels);
5686                 pixels = NULL;
5687         }
5688
5689         mymiplevel = savemiplevel;
5690         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5691         {
5692                 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), mymiplevel, NULL);
5693                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
5694                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true);
5695                 Mem_Free(pixels);
5696                 pixels = NULL;
5697         }
5698
5699         mymiplevel = savemiplevel;
5700         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer, &mymiplevel)))
5701         {
5702                 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), mymiplevel, NULL);
5703                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
5704                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true);
5705                 Mem_Free(pixels);
5706                 pixels = NULL;
5707         }
5708
5709         if (basepixels)
5710                 Mem_Free(basepixels);
5711
5712         return skinframe;
5713 }
5714
5715 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
5716 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
5717 {
5718         int i;
5719         unsigned char *temp1, *temp2;
5720         skinframe_t *skinframe;
5721
5722         if (cls.state == ca_dedicated)
5723                 return NULL;
5724
5725         // if already loaded just return it, otherwise make a new skinframe
5726         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
5727         if (skinframe && skinframe->base)
5728                 return skinframe;
5729
5730         skinframe->stain = NULL;
5731         skinframe->merged = NULL;
5732         skinframe->base = NULL;
5733         skinframe->pants = NULL;
5734         skinframe->shirt = NULL;
5735         skinframe->nmap = NULL;
5736         skinframe->gloss = NULL;
5737         skinframe->glow = NULL;
5738         skinframe->fog = NULL;
5739         skinframe->reflect = NULL;
5740         skinframe->hasalpha = false;
5741
5742         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5743         if (!skindata)
5744                 return NULL;
5745
5746         if (developer_loading.integer)
5747                 Con_Printf("loading 32bit skin \"%s\"\n", name);
5748
5749         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
5750         {
5751                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5752                 temp2 = temp1 + width * height * 4;
5753                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5754                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
5755                 Mem_Free(temp1);
5756         }
5757         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
5758         if (textureflags & TEXF_ALPHA)
5759         {
5760                 for (i = 3;i < width * height * 4;i += 4)
5761                 {
5762                         if (skindata[i] < 255)
5763                         {
5764                                 skinframe->hasalpha = true;
5765                                 break;
5766                         }
5767                 }
5768                 if (r_loadfog && skinframe->hasalpha)
5769                 {
5770                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
5771                         memcpy(fogpixels, skindata, width * height * 4);
5772                         for (i = 0;i < width * height * 4;i += 4)
5773                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
5774                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, skinframe->textureflags, -1, NULL);
5775                         Mem_Free(fogpixels);
5776                 }
5777         }
5778
5779         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
5780         //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]);
5781
5782         return skinframe;
5783 }
5784
5785 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
5786 {
5787         int i;
5788         int featuresmask;
5789         skinframe_t *skinframe;
5790
5791         if (cls.state == ca_dedicated)
5792                 return NULL;
5793
5794         // if already loaded just return it, otherwise make a new skinframe
5795         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5796         if (skinframe && skinframe->base)
5797                 return skinframe;
5798
5799         skinframe->stain = NULL;
5800         skinframe->merged = NULL;
5801         skinframe->base = NULL;
5802         skinframe->pants = NULL;
5803         skinframe->shirt = NULL;
5804         skinframe->nmap = NULL;
5805         skinframe->gloss = NULL;
5806         skinframe->glow = NULL;
5807         skinframe->fog = NULL;
5808         skinframe->reflect = NULL;
5809         skinframe->hasalpha = false;
5810
5811         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5812         if (!skindata)
5813                 return NULL;
5814
5815         if (developer_loading.integer)
5816                 Con_Printf("loading quake skin \"%s\"\n", name);
5817
5818         // 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)
5819         skinframe->qpixels = Mem_Alloc(r_main_mempool, width*height);
5820         memcpy(skinframe->qpixels, skindata, width*height);
5821         skinframe->qwidth = width;
5822         skinframe->qheight = height;
5823
5824         featuresmask = 0;
5825         for (i = 0;i < width * height;i++)
5826                 featuresmask |= palette_featureflags[skindata[i]];
5827
5828         skinframe->hasalpha = false;
5829         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
5830         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
5831         skinframe->qgeneratemerged = true;
5832         skinframe->qgeneratebase = skinframe->qhascolormapping;
5833         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
5834
5835         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
5836         //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]);
5837
5838         return skinframe;
5839 }
5840
5841 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
5842 {
5843         int width;
5844         int height;
5845         unsigned char *skindata;
5846
5847         if (!skinframe->qpixels)
5848                 return;
5849
5850         if (!skinframe->qhascolormapping)
5851                 colormapped = false;
5852
5853         if (colormapped)
5854         {
5855                 if (!skinframe->qgeneratebase)
5856                         return;
5857         }
5858         else
5859         {
5860                 if (!skinframe->qgeneratemerged)
5861                         return;
5862         }
5863
5864         width = skinframe->qwidth;
5865         height = skinframe->qheight;
5866         skindata = skinframe->qpixels;
5867
5868         if (skinframe->qgeneratenmap)
5869         {
5870                 unsigned char *temp1, *temp2;
5871                 skinframe->qgeneratenmap = false;
5872                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
5873                 temp2 = temp1 + width * height * 4;
5874                 // use either a custom palette or the quake palette
5875                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
5876                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
5877                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, skinframe->textureflags | TEXF_ALPHA, -1, NULL);
5878                 Mem_Free(temp1);
5879         }
5880
5881         if (skinframe->qgenerateglow)
5882         {
5883                 skinframe->qgenerateglow = false;
5884                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
5885         }
5886
5887         if (colormapped)
5888         {
5889                 skinframe->qgeneratebase = false;
5890                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
5891                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
5892                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
5893         }
5894         else
5895         {
5896                 skinframe->qgeneratemerged = false;
5897                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
5898         }
5899
5900         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
5901         {
5902                 Mem_Free(skinframe->qpixels);
5903                 skinframe->qpixels = NULL;
5904         }
5905 }
5906
5907 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)
5908 {
5909         int i;
5910         skinframe_t *skinframe;
5911
5912         if (cls.state == ca_dedicated)
5913                 return NULL;
5914
5915         // if already loaded just return it, otherwise make a new skinframe
5916         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
5917         if (skinframe && skinframe->base)
5918                 return skinframe;
5919
5920         skinframe->stain = NULL;
5921         skinframe->merged = NULL;
5922         skinframe->base = NULL;
5923         skinframe->pants = NULL;
5924         skinframe->shirt = NULL;
5925         skinframe->nmap = NULL;
5926         skinframe->gloss = NULL;
5927         skinframe->glow = NULL;
5928         skinframe->fog = NULL;
5929         skinframe->reflect = NULL;
5930         skinframe->hasalpha = false;
5931
5932         // if no data was provided, then clearly the caller wanted to get a blank skinframe
5933         if (!skindata)
5934                 return NULL;
5935
5936         if (developer_loading.integer)
5937                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
5938
5939         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette);
5940         if (textureflags & TEXF_ALPHA)
5941         {
5942                 for (i = 0;i < width * height;i++)
5943                 {
5944                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
5945                         {
5946                                 skinframe->hasalpha = true;
5947                                 break;
5948                         }
5949                 }
5950                 if (r_loadfog && skinframe->hasalpha)
5951                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, alphapalette);
5952         }
5953
5954         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
5955         //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]);
5956
5957         return skinframe;
5958 }
5959
5960 skinframe_t *R_SkinFrame_LoadMissing(void)
5961 {
5962         skinframe_t *skinframe;
5963
5964         if (cls.state == ca_dedicated)
5965                 return NULL;
5966
5967         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
5968         skinframe->stain = NULL;
5969         skinframe->merged = NULL;
5970         skinframe->base = NULL;
5971         skinframe->pants = NULL;
5972         skinframe->shirt = NULL;
5973         skinframe->nmap = NULL;
5974         skinframe->gloss = NULL;
5975         skinframe->glow = NULL;
5976         skinframe->fog = NULL;
5977         skinframe->reflect = NULL;
5978         skinframe->hasalpha = false;
5979
5980         skinframe->avgcolor[0] = rand() / RAND_MAX;
5981         skinframe->avgcolor[1] = rand() / RAND_MAX;
5982         skinframe->avgcolor[2] = rand() / RAND_MAX;
5983         skinframe->avgcolor[3] = 1;
5984
5985         return skinframe;
5986 }
5987
5988 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
5989 typedef struct suffixinfo_s
5990 {
5991         char *suffix;
5992         qboolean flipx, flipy, flipdiagonal;
5993 }
5994 suffixinfo_t;
5995 static suffixinfo_t suffix[3][6] =
5996 {
5997         {
5998                 {"px",   false, false, false},
5999                 {"nx",   false, false, false},
6000                 {"py",   false, false, false},
6001                 {"ny",   false, false, false},
6002                 {"pz",   false, false, false},
6003                 {"nz",   false, false, false}
6004         },
6005         {
6006                 {"posx", false, false, false},
6007                 {"negx", false, false, false},
6008                 {"posy", false, false, false},
6009                 {"negy", false, false, false},
6010                 {"posz", false, false, false},
6011                 {"negz", false, false, false}
6012         },
6013         {
6014                 {"rt",    true, false,  true},
6015                 {"lf",   false,  true,  true},
6016                 {"ft",    true,  true, false},
6017                 {"bk",   false, false, false},
6018                 {"up",    true, false,  true},
6019                 {"dn",    true, false,  true}
6020         }
6021 };
6022
6023 static int componentorder[4] = {0, 1, 2, 3};
6024
6025 rtexture_t *R_LoadCubemap(const char *basename)
6026 {
6027         int i, j, cubemapsize;
6028         unsigned char *cubemappixels, *image_buffer;
6029         rtexture_t *cubemaptexture;
6030         char name[256];
6031         // must start 0 so the first loadimagepixels has no requested width/height
6032         cubemapsize = 0;
6033         cubemappixels = NULL;
6034         cubemaptexture = NULL;
6035         // keep trying different suffix groups (posx, px, rt) until one loads
6036         for (j = 0;j < 3 && !cubemappixels;j++)
6037         {
6038                 // load the 6 images in the suffix group
6039                 for (i = 0;i < 6;i++)
6040                 {
6041                         // generate an image name based on the base and and suffix
6042                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6043                         // load it
6044                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer, NULL)))
6045                         {
6046                                 // an image loaded, make sure width and height are equal
6047                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6048                                 {
6049                                         // if this is the first image to load successfully, allocate the cubemap memory
6050                                         if (!cubemappixels && image_width >= 1)
6051                                         {
6052                                                 cubemapsize = image_width;
6053                                                 // note this clears to black, so unavailable sides are black
6054                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6055                                         }
6056                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6057                                         if (cubemappixels)
6058                                                 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);
6059                                 }
6060                                 else
6061                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6062                                 // free the image
6063                                 Mem_Free(image_buffer);
6064                         }
6065                 }
6066         }
6067         // if a cubemap loaded, upload it
6068         if (cubemappixels)
6069         {
6070                 if (developer_loading.integer)
6071                         Con_Printf("loading cubemap \"%s\"\n", basename);
6072
6073                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6074                 Mem_Free(cubemappixels);
6075         }
6076         else
6077         {
6078                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6079                 if (developer_loading.integer)
6080                 {
6081                         Con_Printf("(tried tried images ");
6082                         for (j = 0;j < 3;j++)
6083                                 for (i = 0;i < 6;i++)
6084                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6085                         Con_Print(" and was unable to find any of them).\n");
6086                 }
6087         }
6088         return cubemaptexture;
6089 }
6090
6091 rtexture_t *R_GetCubemap(const char *basename)
6092 {
6093         int i;
6094         for (i = 0;i < r_texture_numcubemaps;i++)
6095                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6096                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6097         if (i >= MAX_CUBEMAPS)
6098                 return r_texture_whitecube;
6099         r_texture_numcubemaps++;
6100         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6101         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6102         return r_texture_cubemaps[i].texture;
6103 }
6104
6105 void R_FreeCubemaps(void)
6106 {
6107         int i;
6108         for (i = 0;i < r_texture_numcubemaps;i++)
6109         {
6110                 if (developer_loading.integer)
6111                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6112                 if (r_texture_cubemaps[i].texture)
6113                         R_FreeTexture(r_texture_cubemaps[i].texture);
6114         }
6115         r_texture_numcubemaps = 0;
6116 }
6117
6118 void R_Main_FreeViewCache(void)
6119 {
6120         if (r_refdef.viewcache.entityvisible)
6121                 Mem_Free(r_refdef.viewcache.entityvisible);
6122         if (r_refdef.viewcache.world_pvsbits)
6123                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6124         if (r_refdef.viewcache.world_leafvisible)
6125                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6126         if (r_refdef.viewcache.world_surfacevisible)
6127                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6128         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6129 }
6130
6131 void R_Main_ResizeViewCache(void)
6132 {
6133         int numentities = r_refdef.scene.numentities;
6134         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6135         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6136         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6137         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6138         if (r_refdef.viewcache.maxentities < numentities)
6139         {
6140                 r_refdef.viewcache.maxentities = numentities;
6141                 if (r_refdef.viewcache.entityvisible)
6142                         Mem_Free(r_refdef.viewcache.entityvisible);
6143                 r_refdef.viewcache.entityvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6144         }
6145         if (r_refdef.viewcache.world_numclusters != numclusters)
6146         {
6147                 r_refdef.viewcache.world_numclusters = numclusters;
6148                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6149                 if (r_refdef.viewcache.world_pvsbits)
6150                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6151                 r_refdef.viewcache.world_pvsbits = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6152         }
6153         if (r_refdef.viewcache.world_numleafs != numleafs)
6154         {
6155                 r_refdef.viewcache.world_numleafs = numleafs;
6156                 if (r_refdef.viewcache.world_leafvisible)
6157                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6158                 r_refdef.viewcache.world_leafvisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6159         }
6160         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6161         {
6162                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6163                 if (r_refdef.viewcache.world_surfacevisible)
6164                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6165                 r_refdef.viewcache.world_surfacevisible = Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6166         }
6167 }
6168
6169 extern rtexture_t *loadingscreentexture;
6170 void gl_main_start(void)
6171 {
6172         loadingscreentexture = NULL;
6173         r_texture_blanknormalmap = NULL;
6174         r_texture_white = NULL;
6175         r_texture_grey128 = NULL;
6176         r_texture_black = NULL;
6177         r_texture_whitecube = NULL;
6178         r_texture_normalizationcube = NULL;
6179         r_texture_fogattenuation = NULL;
6180         r_texture_fogheighttexture = NULL;
6181         r_texture_gammaramps = NULL;
6182         r_texture_numcubemaps = 0;
6183
6184         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6185         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6186
6187         switch(vid.renderpath)
6188         {
6189         case RENDERPATH_GL20:
6190         case RENDERPATH_CGGL:
6191                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6192                 Cvar_SetValueQuick(&gl_combine, 1);
6193                 Cvar_SetValueQuick(&r_glsl, 1);
6194                 r_loadnormalmap = true;
6195                 r_loadgloss = true;
6196                 r_loadfog = false;
6197                 break;
6198         case RENDERPATH_GL13:
6199                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6200                 Cvar_SetValueQuick(&gl_combine, 1);
6201                 Cvar_SetValueQuick(&r_glsl, 0);
6202                 r_loadnormalmap = false;
6203                 r_loadgloss = false;
6204                 r_loadfog = true;
6205                 break;
6206         case RENDERPATH_GL11:
6207                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6208                 Cvar_SetValueQuick(&gl_combine, 0);
6209                 Cvar_SetValueQuick(&r_glsl, 0);
6210                 r_loadnormalmap = false;
6211                 r_loadgloss = false;
6212                 r_loadfog = true;
6213                 break;
6214         }
6215
6216         R_AnimCache_Free();
6217         R_FrameData_Reset();
6218
6219         r_numqueries = 0;
6220         r_maxqueries = 0;
6221         memset(r_queries, 0, sizeof(r_queries));
6222
6223         r_qwskincache = NULL;
6224         r_qwskincache_size = 0;
6225
6226         // set up r_skinframe loading system for textures
6227         memset(&r_skinframe, 0, sizeof(r_skinframe));
6228         r_skinframe.loadsequence = 1;
6229         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6230
6231         r_main_texturepool = R_AllocTexturePool();
6232         R_BuildBlankTextures();
6233         R_BuildNoTexture();
6234         if (vid.support.arb_texture_cube_map)
6235         {
6236                 R_BuildWhiteCube();
6237                 R_BuildNormalizationCube();
6238         }
6239         r_texture_fogattenuation = NULL;
6240         r_texture_fogheighttexture = NULL;
6241         r_texture_gammaramps = NULL;
6242         //r_texture_fogintensity = NULL;
6243         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6244         memset(&r_waterstate, 0, sizeof(r_waterstate));
6245         r_glsl_permutation = NULL;
6246         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6247         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6248         glslshaderstring = NULL;
6249 #ifdef SUPPORTCG
6250         r_cg_permutation = NULL;
6251         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6252         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
6253         cgshaderstring = NULL;
6254 #endif
6255         memset(&r_svbsp, 0, sizeof (r_svbsp));
6256
6257         r_refdef.fogmasktable_density = 0;
6258 }
6259
6260 void gl_main_shutdown(void)
6261 {
6262         R_AnimCache_Free();
6263         R_FrameData_Reset();
6264
6265         R_Main_FreeViewCache();
6266
6267         if (r_maxqueries)
6268                 qglDeleteQueriesARB(r_maxqueries, r_queries);
6269
6270         r_numqueries = 0;
6271         r_maxqueries = 0;
6272         memset(r_queries, 0, sizeof(r_queries));
6273
6274         r_qwskincache = NULL;
6275         r_qwskincache_size = 0;
6276
6277         // clear out the r_skinframe state
6278         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6279         memset(&r_skinframe, 0, sizeof(r_skinframe));
6280
6281         if (r_svbsp.nodes)
6282                 Mem_Free(r_svbsp.nodes);
6283         memset(&r_svbsp, 0, sizeof (r_svbsp));
6284         R_FreeTexturePool(&r_main_texturepool);
6285         loadingscreentexture = NULL;
6286         r_texture_blanknormalmap = NULL;
6287         r_texture_white = NULL;
6288         r_texture_grey128 = NULL;
6289         r_texture_black = NULL;
6290         r_texture_whitecube = NULL;
6291         r_texture_normalizationcube = NULL;
6292         r_texture_fogattenuation = NULL;
6293         r_texture_fogheighttexture = NULL;
6294         r_texture_gammaramps = NULL;
6295         r_texture_numcubemaps = 0;
6296         //r_texture_fogintensity = NULL;
6297         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6298         memset(&r_waterstate, 0, sizeof(r_waterstate));
6299         r_glsl_permutation = NULL;
6300         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6301         glslshaderstring = NULL;
6302 #ifdef SUPPORTCG
6303         r_cg_permutation = NULL;
6304         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
6305         cgshaderstring = NULL;
6306 #endif
6307         R_GLSL_Restart_f();
6308 }
6309
6310 extern void CL_ParseEntityLump(char *entitystring);
6311 void gl_main_newmap(void)
6312 {
6313         // FIXME: move this code to client
6314         char *entities, entname[MAX_QPATH];
6315         if (r_qwskincache)
6316                 Mem_Free(r_qwskincache);
6317         r_qwskincache = NULL;
6318         r_qwskincache_size = 0;
6319         if (cl.worldmodel)
6320         {
6321                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6322                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6323                 {
6324                         CL_ParseEntityLump(entities);
6325                         Mem_Free(entities);
6326                         return;
6327                 }
6328                 if (cl.worldmodel->brush.entities)
6329                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6330         }
6331         R_Main_FreeViewCache();
6332
6333         R_FrameData_Reset();
6334 }
6335
6336 void GL_Main_Init(void)
6337 {
6338         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6339
6340         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6341         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6342         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6343         if (gamemode == GAME_NEHAHRA)
6344         {
6345                 Cvar_RegisterVariable (&gl_fogenable);
6346                 Cvar_RegisterVariable (&gl_fogdensity);
6347                 Cvar_RegisterVariable (&gl_fogred);
6348                 Cvar_RegisterVariable (&gl_foggreen);
6349                 Cvar_RegisterVariable (&gl_fogblue);
6350                 Cvar_RegisterVariable (&gl_fogstart);
6351                 Cvar_RegisterVariable (&gl_fogend);
6352                 Cvar_RegisterVariable (&gl_skyclip);
6353         }
6354         Cvar_RegisterVariable(&r_motionblur);
6355         Cvar_RegisterVariable(&r_motionblur_maxblur);
6356         Cvar_RegisterVariable(&r_motionblur_bmin);
6357         Cvar_RegisterVariable(&r_motionblur_vmin);
6358         Cvar_RegisterVariable(&r_motionblur_vmax);
6359         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6360         Cvar_RegisterVariable(&r_motionblur_randomize);
6361         Cvar_RegisterVariable(&r_damageblur);
6362         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6363         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6364         Cvar_RegisterVariable(&r_equalize_entities_by);
6365         Cvar_RegisterVariable(&r_equalize_entities_to);
6366         Cvar_RegisterVariable(&r_depthfirst);
6367         Cvar_RegisterVariable(&r_useinfinitefarclip);
6368         Cvar_RegisterVariable(&r_farclip_base);
6369         Cvar_RegisterVariable(&r_farclip_world);
6370         Cvar_RegisterVariable(&r_nearclip);
6371         Cvar_RegisterVariable(&r_showbboxes);
6372         Cvar_RegisterVariable(&r_showsurfaces);
6373         Cvar_RegisterVariable(&r_showtris);
6374         Cvar_RegisterVariable(&r_shownormals);
6375         Cvar_RegisterVariable(&r_showlighting);
6376         Cvar_RegisterVariable(&r_showshadowvolumes);
6377         Cvar_RegisterVariable(&r_showcollisionbrushes);
6378         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6379         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6380         Cvar_RegisterVariable(&r_showdisabledepthtest);
6381         Cvar_RegisterVariable(&r_drawportals);
6382         Cvar_RegisterVariable(&r_drawentities);
6383         Cvar_RegisterVariable(&r_draw2d);
6384         Cvar_RegisterVariable(&r_drawworld);
6385         Cvar_RegisterVariable(&r_cullentities_trace);
6386         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6387         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6388         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6389         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6390         Cvar_RegisterVariable(&r_drawviewmodel);
6391         Cvar_RegisterVariable(&r_drawexteriormodel);
6392         Cvar_RegisterVariable(&r_speeds);
6393         Cvar_RegisterVariable(&r_fullbrights);
6394         Cvar_RegisterVariable(&r_wateralpha);
6395         Cvar_RegisterVariable(&r_dynamic);
6396         Cvar_RegisterVariable(&r_fullbright);
6397         Cvar_RegisterVariable(&r_shadows);
6398         Cvar_RegisterVariable(&r_shadows_darken);
6399         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6400         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6401         Cvar_RegisterVariable(&r_shadows_throwdistance);
6402         Cvar_RegisterVariable(&r_shadows_throwdirection);
6403         Cvar_RegisterVariable(&r_shadows_focus);
6404         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6405         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6406         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6407         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6408         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6409         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6410         Cvar_RegisterVariable(&r_fog_exp2);
6411         Cvar_RegisterVariable(&r_drawfog);
6412         Cvar_RegisterVariable(&r_transparentdepthmasking);
6413         Cvar_RegisterVariable(&r_texture_dds_load);
6414         Cvar_RegisterVariable(&r_texture_dds_save);
6415         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6416         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6417         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6418         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6419         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6420         Cvar_RegisterVariable(&r_textureunits);
6421         Cvar_RegisterVariable(&gl_combine);
6422         Cvar_RegisterVariable(&r_glsl);
6423         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6424         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6425         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6426         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6427         Cvar_RegisterVariable(&r_glsl_postprocess);
6428         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6429         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6430         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6431         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6432         Cvar_RegisterVariable(&r_water);
6433         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6434         Cvar_RegisterVariable(&r_water_clippingplanebias);
6435         Cvar_RegisterVariable(&r_water_refractdistort);
6436         Cvar_RegisterVariable(&r_water_reflectdistort);
6437         Cvar_RegisterVariable(&r_lerpsprites);
6438         Cvar_RegisterVariable(&r_lerpmodels);
6439         Cvar_RegisterVariable(&r_lerplightstyles);
6440         Cvar_RegisterVariable(&r_waterscroll);
6441         Cvar_RegisterVariable(&r_bloom);
6442         Cvar_RegisterVariable(&r_bloom_colorscale);
6443         Cvar_RegisterVariable(&r_bloom_brighten);
6444         Cvar_RegisterVariable(&r_bloom_blur);
6445         Cvar_RegisterVariable(&r_bloom_resolution);
6446         Cvar_RegisterVariable(&r_bloom_colorexponent);
6447         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6448         Cvar_RegisterVariable(&r_hdr);
6449         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6450         Cvar_RegisterVariable(&r_hdr_glowintensity);
6451         Cvar_RegisterVariable(&r_hdr_range);
6452         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6453         Cvar_RegisterVariable(&developer_texturelogging);
6454         Cvar_RegisterVariable(&gl_lightmaps);
6455         Cvar_RegisterVariable(&r_test);
6456         Cvar_RegisterVariable(&r_glsl_saturation);
6457         Cvar_RegisterVariable(&r_framedatasize);
6458         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6459                 Cvar_SetValue("r_fullbrights", 0);
6460         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
6461
6462         Cvar_RegisterVariable(&r_track_sprites);
6463         Cvar_RegisterVariable(&r_track_sprites_flags);
6464         Cvar_RegisterVariable(&r_track_sprites_scalew);
6465         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6466         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6467         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6468 }
6469
6470 extern void R_Textures_Init(void);
6471 extern void GL_Draw_Init(void);
6472 extern void GL_Main_Init(void);
6473 extern void R_Shadow_Init(void);
6474 extern void R_Sky_Init(void);
6475 extern void GL_Surf_Init(void);
6476 extern void R_Particles_Init(void);
6477 extern void R_Explosion_Init(void);
6478 extern void gl_backend_init(void);
6479 extern void Sbar_Init(void);
6480 extern void R_LightningBeams_Init(void);
6481 extern void Mod_RenderInit(void);
6482 extern void Font_Init(void);
6483
6484 void Render_Init(void)
6485 {
6486         gl_backend_init();
6487         R_Textures_Init();
6488         GL_Main_Init();
6489         Font_Init();
6490         GL_Draw_Init();
6491         R_Shadow_Init();
6492         R_Sky_Init();
6493         GL_Surf_Init();
6494         Sbar_Init();
6495         R_Particles_Init();
6496         R_Explosion_Init();
6497         R_LightningBeams_Init();
6498         Mod_RenderInit();
6499 }
6500
6501 /*
6502 ===============
6503 GL_Init
6504 ===============
6505 */
6506 extern char *ENGINE_EXTENSIONS;
6507 void GL_Init (void)
6508 {
6509         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6510         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6511         gl_version = (const char *)qglGetString(GL_VERSION);
6512         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6513
6514         if (!gl_extensions)
6515                 gl_extensions = "";
6516         if (!gl_platformextensions)
6517                 gl_platformextensions = "";
6518
6519         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6520         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6521         Con_Printf("GL_VERSION: %s\n", gl_version);
6522         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6523         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6524
6525         VID_CheckExtensions();
6526
6527         // LordHavoc: report supported extensions
6528         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6529
6530         // clear to black (loading plaque will be seen over this)
6531         CHECKGLERROR
6532         qglClearColor(0,0,0,1);CHECKGLERROR
6533         qglClear(GL_COLOR_BUFFER_BIT);CHECKGLERROR
6534 }
6535
6536 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6537 {
6538         int i;
6539         mplane_t *p;
6540         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6541         {
6542                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6543                 if (i == 4)
6544                         continue;
6545                 p = r_refdef.view.frustum + i;
6546                 switch(p->signbits)
6547                 {
6548                 default:
6549                 case 0:
6550                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6551                                 return true;
6552                         break;
6553                 case 1:
6554                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6555                                 return true;
6556                         break;
6557                 case 2:
6558                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6559                                 return true;
6560                         break;
6561                 case 3:
6562                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6563                                 return true;
6564                         break;
6565                 case 4:
6566                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6567                                 return true;
6568                         break;
6569                 case 5:
6570                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6571                                 return true;
6572                         break;
6573                 case 6:
6574                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6575                                 return true;
6576                         break;
6577                 case 7:
6578                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6579                                 return true;
6580                         break;
6581                 }
6582         }
6583         return false;
6584 }
6585
6586 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
6587 {
6588         int i;
6589         const mplane_t *p;
6590         for (i = 0;i < numplanes;i++)
6591         {
6592                 p = planes + i;
6593                 switch(p->signbits)
6594                 {
6595                 default:
6596                 case 0:
6597                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6598                                 return true;
6599                         break;
6600                 case 1:
6601                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6602                                 return true;
6603                         break;
6604                 case 2:
6605                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6606                                 return true;
6607                         break;
6608                 case 3:
6609                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
6610                                 return true;
6611                         break;
6612                 case 4:
6613                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6614                                 return true;
6615                         break;
6616                 case 5:
6617                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
6618                                 return true;
6619                         break;
6620                 case 6:
6621                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6622                                 return true;
6623                         break;
6624                 case 7:
6625                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
6626                                 return true;
6627                         break;
6628                 }
6629         }
6630         return false;
6631 }
6632
6633 //==================================================================================
6634
6635 // LordHavoc: this stores temporary data used within the same frame
6636
6637 qboolean r_framedata_failed;
6638 static size_t r_framedata_size;
6639 static size_t r_framedata_current;
6640 static void *r_framedata_base;
6641
6642 void R_FrameData_Reset(void)
6643 {
6644         if (r_framedata_base)
6645                 Mem_Free(r_framedata_base);
6646         r_framedata_base = NULL;
6647         r_framedata_size = 0;
6648         r_framedata_current = 0;
6649         r_framedata_failed = false;
6650 }
6651
6652 void R_FrameData_NewFrame(void)
6653 {
6654         size_t wantedsize;
6655         if (r_framedata_failed)
6656                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
6657         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
6658         wantedsize = bound(65536, wantedsize, 128*1024*1024);
6659         if (r_framedata_size != wantedsize)
6660         {
6661                 r_framedata_size = wantedsize;
6662                 if (r_framedata_base)
6663                         Mem_Free(r_framedata_base);
6664                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
6665         }
6666         r_framedata_current = 0;
6667         r_framedata_failed = false;
6668 }
6669
6670 void *R_FrameData_Alloc(size_t size)
6671 {
6672         void *data;
6673
6674         // align to 16 byte boundary
6675         size = (size + 15) & ~15;
6676         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
6677         r_framedata_current += size;
6678
6679         // check overflow
6680         if (r_framedata_current > r_framedata_size)
6681                 r_framedata_failed = true;
6682
6683         // return NULL on everything after a failure
6684         if (r_framedata_failed)
6685                 return NULL;
6686
6687         return data;
6688 }
6689
6690 void *R_FrameData_Store(size_t size, void *data)
6691 {
6692         void *d = R_FrameData_Alloc(size);
6693         if (d)
6694                 memcpy(d, data, size);
6695         return d;
6696 }
6697
6698 //==================================================================================
6699
6700 // LordHavoc: animcache originally written by Echon, rewritten since then
6701
6702 /**
6703  * Animation cache prevents re-generating mesh data for an animated model
6704  * multiple times in one frame for lighting, shadowing, reflections, etc.
6705  */
6706
6707 void R_AnimCache_Free(void)
6708 {
6709 }
6710
6711 void R_AnimCache_ClearCache(void)
6712 {
6713         int i;
6714         entity_render_t *ent;
6715
6716         for (i = 0;i < r_refdef.scene.numentities;i++)
6717         {
6718                 ent = r_refdef.scene.entities[i];
6719                 ent->animcache_vertex3f = NULL;
6720                 ent->animcache_normal3f = NULL;
6721                 ent->animcache_svector3f = NULL;
6722                 ent->animcache_tvector3f = NULL;
6723                 ent->animcache_vertexposition = NULL;
6724                 ent->animcache_vertexmesh = NULL;
6725                 ent->animcache_vertexpositionbuffer = NULL;
6726                 ent->animcache_vertexmeshbuffer = NULL;
6727         }
6728 }
6729
6730 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
6731 {
6732         int i;
6733         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
6734                 ent->animcache_vertexmesh = R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
6735         if (!ent->animcache_vertexposition)
6736                 ent->animcache_vertexposition = R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
6737         if (ent->animcache_vertexposition)
6738         {
6739                 for (i = 0;i < numvertices;i++)
6740                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexposition[i].vertex3f);
6741                 // TODO: upload vertex buffer?
6742         }
6743         if (ent->animcache_vertexmesh)
6744         {
6745                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
6746                 for (i = 0;i < numvertices;i++)
6747                         VectorCopy(ent->animcache_vertex3f + 3*i, ent->animcache_vertexmesh[i].vertex3f);
6748                 if (ent->animcache_svector3f)
6749                         for (i = 0;i < numvertices;i++)
6750                                 VectorCopy(ent->animcache_svector3f + 3*i, ent->animcache_vertexmesh[i].svector3f);
6751                 if (ent->animcache_tvector3f)
6752                         for (i = 0;i < numvertices;i++)
6753                                 VectorCopy(ent->animcache_tvector3f + 3*i, ent->animcache_vertexmesh[i].tvector3f);
6754                 if (ent->animcache_normal3f)
6755                         for (i = 0;i < numvertices;i++)
6756                                 VectorCopy(ent->animcache_normal3f + 3*i, ent->animcache_vertexmesh[i].normal3f);
6757                 // TODO: upload vertex buffer?
6758         }
6759 }
6760
6761 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
6762 {
6763         dp_model_t *model = ent->model;
6764         int numvertices;
6765         // see if it's already cached this frame
6766         if (ent->animcache_vertex3f)
6767         {
6768                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
6769                 if (wantnormals || wanttangents)
6770                 {
6771                         if (ent->animcache_normal3f)
6772                                 wantnormals = false;
6773                         if (ent->animcache_svector3f)
6774                                 wanttangents = false;
6775                         if (wantnormals || wanttangents)
6776                         {
6777                                 numvertices = model->surfmesh.num_vertices;
6778                                 if (wantnormals)
6779                                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6780                                 if (wanttangents)
6781                                 {
6782                                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6783                                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6784                                 }
6785                                 if (!r_framedata_failed)
6786                                 {
6787                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
6788                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6789                                 }
6790                         }
6791                 }
6792         }
6793         else
6794         {
6795                 // see if this ent is worth caching
6796                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
6797                         return false;
6798                 // get some memory for this entity and generate mesh data
6799                 numvertices = model->surfmesh.num_vertices;
6800                 ent->animcache_vertex3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6801                 if (wantnormals)
6802                         ent->animcache_normal3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6803                 if (wanttangents)
6804                 {
6805                         ent->animcache_svector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6806                         ent->animcache_tvector3f = R_FrameData_Alloc(sizeof(float[3])*numvertices);
6807                 }
6808                 if (!r_framedata_failed)
6809                 {
6810                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
6811                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
6812                 }
6813         }
6814         return !r_framedata_failed;
6815 }
6816
6817 void R_AnimCache_CacheVisibleEntities(void)
6818 {
6819         int i;
6820         qboolean wantnormals = true;
6821         qboolean wanttangents = !r_showsurfaces.integer;
6822
6823         switch(vid.renderpath)
6824         {
6825         case RENDERPATH_GL20:
6826         case RENDERPATH_CGGL:
6827                 break;
6828         case RENDERPATH_GL13:
6829         case RENDERPATH_GL11:
6830                 wanttangents = false;
6831                 break;
6832         }
6833
6834         if (r_shownormals.integer)
6835                 wanttangents = wantnormals = true;
6836
6837         // TODO: thread this
6838         // NOTE: R_PrepareRTLights() also caches entities
6839
6840         for (i = 0;i < r_refdef.scene.numentities;i++)
6841                 if (r_refdef.viewcache.entityvisible[i])
6842                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
6843 }
6844
6845 //==================================================================================
6846
6847 static void R_View_UpdateEntityLighting (void)
6848 {
6849         int i;
6850         entity_render_t *ent;
6851         vec3_t tempdiffusenormal, avg;
6852         vec_t f, fa, fd, fdd;
6853         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
6854
6855         for (i = 0;i < r_refdef.scene.numentities;i++)
6856         {
6857                 ent = r_refdef.scene.entities[i];
6858
6859                 // skip unseen models
6860                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
6861                         continue;
6862
6863                 // skip bsp models
6864                 if (ent->model && ent->model->brush.num_leafs)
6865                 {
6866                         // TODO: use modellight for r_ambient settings on world?
6867                         VectorSet(ent->modellight_ambient, 0, 0, 0);
6868                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
6869                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
6870                         continue;
6871                 }
6872
6873                 // fetch the lighting from the worldmodel data
6874                 VectorClear(ent->modellight_ambient);
6875                 VectorClear(ent->modellight_diffuse);
6876                 VectorClear(tempdiffusenormal);
6877                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
6878                 {
6879                         vec3_t org;
6880                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6881                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
6882                         if(ent->flags & RENDER_EQUALIZE)
6883                         {
6884                                 // first fix up ambient lighting...
6885                                 if(r_equalize_entities_minambient.value > 0)
6886                                 {
6887                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
6888                                         if(fd > 0)
6889                                         {
6890                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
6891                                                 if(fa < r_equalize_entities_minambient.value * fd)
6892                                                 {
6893                                                         // solve:
6894                                                         //   fa'/fd' = minambient
6895                                                         //   fa'+0.25*fd' = fa+0.25*fd
6896                                                         //   ...
6897                                                         //   fa' = fd' * minambient
6898                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
6899                                                         //   ...
6900                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
6901                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
6902                                                         //   ...
6903                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
6904                                                         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
6905                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
6906                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6907                                                 }
6908                                         }
6909                                 }
6910
6911                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
6912                                 {
6913                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
6914                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
6915                                         if(f > 0)
6916                                         {
6917                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
6918                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
6919                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
6920                                         }
6921                                 }
6922                         }
6923                 }
6924                 else // highly rare
6925                         VectorSet(ent->modellight_ambient, 1, 1, 1);
6926
6927                 // move the light direction into modelspace coordinates for lighting code
6928                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
6929                 if(VectorLength2(ent->modellight_lightdir) == 0)
6930                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
6931                 VectorNormalize(ent->modellight_lightdir);
6932         }
6933 }
6934
6935 #define MAX_LINEOFSIGHTTRACES 64
6936
6937 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
6938 {
6939         int i;
6940         vec3_t boxmins, boxmaxs;
6941         vec3_t start;
6942         vec3_t end;
6943         dp_model_t *model = r_refdef.scene.worldmodel;
6944
6945         if (!model || !model->brush.TraceLineOfSight)
6946                 return true;
6947
6948         // expand the box a little
6949         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
6950         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
6951         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
6952         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
6953         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
6954         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
6955
6956         // return true if eye is inside enlarged box
6957         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
6958                 return true;
6959
6960         // try center
6961         VectorCopy(eye, start);
6962         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
6963         if (model->brush.TraceLineOfSight(model, start, end))
6964                 return true;
6965
6966         // try various random positions
6967         for (i = 0;i < numsamples;i++)
6968         {
6969                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
6970                 if (model->brush.TraceLineOfSight(model, start, end))
6971                         return true;
6972         }
6973
6974         return false;
6975 }
6976
6977
6978 static void R_View_UpdateEntityVisible (void)
6979 {
6980         int i;
6981         int renderimask;
6982         int samples;
6983         entity_render_t *ent;
6984
6985         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6986                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
6987                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
6988                 :                                                          RENDER_EXTERIORMODEL;
6989         if (!r_drawviewmodel.integer)
6990                 renderimask |= RENDER_VIEWMODEL;
6991         if (!r_drawexteriormodel.integer)
6992                 renderimask |= RENDER_EXTERIORMODEL;
6993         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
6994         {
6995                 // worldmodel can check visibility
6996                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
6997                 for (i = 0;i < r_refdef.scene.numentities;i++)
6998                 {
6999                         ent = r_refdef.scene.entities[i];
7000                         if (!(ent->flags & renderimask))
7001                         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)))
7002                         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))
7003                                 r_refdef.viewcache.entityvisible[i] = true;
7004                 }
7005                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7006                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7007                 {
7008                         for (i = 0;i < r_refdef.scene.numentities;i++)
7009                         {
7010                                 ent = r_refdef.scene.entities[i];
7011                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7012                                 {
7013                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7014                                         if (samples < 0)
7015                                                 continue; // temp entities do pvs only
7016                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7017                                                 ent->last_trace_visibility = realtime;
7018                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7019                                                 r_refdef.viewcache.entityvisible[i] = 0;
7020                                 }
7021                         }
7022                 }
7023         }
7024         else
7025         {
7026                 // no worldmodel or it can't check visibility
7027                 for (i = 0;i < r_refdef.scene.numentities;i++)
7028                 {
7029                         ent = r_refdef.scene.entities[i];
7030                         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));
7031                 }
7032         }
7033 }
7034
7035 /// only used if skyrendermasked, and normally returns false
7036 int R_DrawBrushModelsSky (void)
7037 {
7038         int i, sky;
7039         entity_render_t *ent;
7040
7041         sky = false;
7042         for (i = 0;i < r_refdef.scene.numentities;i++)
7043         {
7044                 if (!r_refdef.viewcache.entityvisible[i])
7045                         continue;
7046                 ent = r_refdef.scene.entities[i];
7047                 if (!ent->model || !ent->model->DrawSky)
7048                         continue;
7049                 ent->model->DrawSky(ent);
7050                 sky = true;
7051         }
7052         return sky;
7053 }
7054
7055 static void R_DrawNoModel(entity_render_t *ent);
7056 static void R_DrawModels(void)
7057 {
7058         int i;
7059         entity_render_t *ent;
7060
7061         for (i = 0;i < r_refdef.scene.numentities;i++)
7062         {
7063                 if (!r_refdef.viewcache.entityvisible[i])
7064                         continue;
7065                 ent = r_refdef.scene.entities[i];
7066                 r_refdef.stats.entities++;
7067                 if (ent->model && ent->model->Draw != NULL)
7068                         ent->model->Draw(ent);
7069                 else
7070                         R_DrawNoModel(ent);
7071         }
7072 }
7073
7074 static void R_DrawModelsDepth(void)
7075 {
7076         int i;
7077         entity_render_t *ent;
7078
7079         for (i = 0;i < r_refdef.scene.numentities;i++)
7080         {
7081                 if (!r_refdef.viewcache.entityvisible[i])
7082                         continue;
7083                 ent = r_refdef.scene.entities[i];
7084                 if (ent->model && ent->model->DrawDepth != NULL)
7085                         ent->model->DrawDepth(ent);
7086         }
7087 }
7088
7089 static void R_DrawModelsDebug(void)
7090 {
7091         int i;
7092         entity_render_t *ent;
7093
7094         for (i = 0;i < r_refdef.scene.numentities;i++)
7095         {
7096                 if (!r_refdef.viewcache.entityvisible[i])
7097                         continue;
7098                 ent = r_refdef.scene.entities[i];
7099                 if (ent->model && ent->model->DrawDebug != NULL)
7100                         ent->model->DrawDebug(ent);
7101         }
7102 }
7103
7104 static void R_DrawModelsAddWaterPlanes(void)
7105 {
7106         int i;
7107         entity_render_t *ent;
7108
7109         for (i = 0;i < r_refdef.scene.numentities;i++)
7110         {
7111                 if (!r_refdef.viewcache.entityvisible[i])
7112                         continue;
7113                 ent = r_refdef.scene.entities[i];
7114                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7115                         ent->model->DrawAddWaterPlanes(ent);
7116         }
7117 }
7118
7119 static void R_View_SetFrustum(void)
7120 {
7121         int i;
7122         double slopex, slopey;
7123         vec3_t forward, left, up, origin;
7124
7125         // we can't trust r_refdef.view.forward and friends in reflected scenes
7126         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7127
7128 #if 0
7129         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7130         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7131         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7132         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7133         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7134         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7135         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7136         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7137         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7138         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7139         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7140         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7141 #endif
7142
7143 #if 0
7144         zNear = r_refdef.nearclip;
7145         nudge = 1.0 - 1.0 / (1<<23);
7146         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7147         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7148         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7149         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7150         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7151         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7152         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7153         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7154 #endif
7155
7156
7157
7158 #if 0
7159         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7160         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7161         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7162         r_refdef.view.frustum[0].dist = m[15] - m[12];
7163
7164         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7165         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7166         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7167         r_refdef.view.frustum[1].dist = m[15] + m[12];
7168
7169         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7170         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7171         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7172         r_refdef.view.frustum[2].dist = m[15] - m[13];
7173
7174         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7175         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7176         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7177         r_refdef.view.frustum[3].dist = m[15] + m[13];
7178
7179         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7180         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7181         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7182         r_refdef.view.frustum[4].dist = m[15] - m[14];
7183
7184         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7185         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7186         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7187         r_refdef.view.frustum[5].dist = m[15] + m[14];
7188 #endif
7189
7190         if (r_refdef.view.useperspective)
7191         {
7192                 slopex = 1.0 / r_refdef.view.frustum_x;
7193                 slopey = 1.0 / r_refdef.view.frustum_y;
7194                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
7195                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
7196                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
7197                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
7198                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7199
7200                 // Leaving those out was a mistake, those were in the old code, and they
7201                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7202                 // I couldn't reproduce it after adding those normalizations. --blub
7203                 VectorNormalize(r_refdef.view.frustum[0].normal);
7204                 VectorNormalize(r_refdef.view.frustum[1].normal);
7205                 VectorNormalize(r_refdef.view.frustum[2].normal);
7206                 VectorNormalize(r_refdef.view.frustum[3].normal);
7207
7208                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7209                 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]);
7210                 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]);
7211                 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]);
7212                 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]);
7213
7214                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7215                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7216                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7217                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7218                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7219         }
7220         else
7221         {
7222                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7223                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7224                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7225                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7226                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7227                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7228                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7229                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7230                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7231                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7232         }
7233         r_refdef.view.numfrustumplanes = 5;
7234
7235         if (r_refdef.view.useclipplane)
7236         {
7237                 r_refdef.view.numfrustumplanes = 6;
7238                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7239         }
7240
7241         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7242                 PlaneClassify(r_refdef.view.frustum + i);
7243
7244         // LordHavoc: note to all quake engine coders, Quake had a special case
7245         // for 90 degrees which assumed a square view (wrong), so I removed it,
7246         // Quake2 has it disabled as well.
7247
7248         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7249         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7250         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7251         //PlaneClassify(&frustum[0]);
7252
7253         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7254         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7255         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7256         //PlaneClassify(&frustum[1]);
7257
7258         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7259         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7260         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7261         //PlaneClassify(&frustum[2]);
7262
7263         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7264         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7265         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7266         //PlaneClassify(&frustum[3]);
7267
7268         // nearclip plane
7269         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7270         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7271         //PlaneClassify(&frustum[4]);
7272 }
7273
7274 void R_View_Update(void)
7275 {
7276         R_Main_ResizeViewCache();
7277         R_View_SetFrustum();
7278         R_View_WorldVisibility(r_refdef.view.useclipplane);
7279         R_View_UpdateEntityVisible();
7280         R_View_UpdateEntityLighting();
7281 }
7282
7283 void R_SetupView(qboolean allowwaterclippingplane)
7284 {
7285         const float *customclipplane = NULL;
7286         float plane[4];
7287         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7288         {
7289                 // LordHavoc: couldn't figure out how to make this approach the
7290                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7291                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7292                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7293                         dist = r_refdef.view.clipplane.dist;
7294                 plane[0] = r_refdef.view.clipplane.normal[0];
7295                 plane[1] = r_refdef.view.clipplane.normal[1];
7296                 plane[2] = r_refdef.view.clipplane.normal[2];
7297                 plane[3] = dist;
7298                 customclipplane = plane;
7299         }
7300
7301         if (!r_refdef.view.useperspective)
7302                 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);
7303         else if (vid.stencil && r_useinfinitefarclip.integer)
7304                 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);
7305         else
7306                 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);
7307         R_SetViewport(&r_refdef.view.viewport);
7308 }
7309
7310 void R_EntityMatrix(const matrix4x4_t *matrix)
7311 {
7312         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7313         {
7314                 gl_modelmatrixchanged = false;
7315                 gl_modelmatrix = *matrix;
7316                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7317                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7318                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7319                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7320                 CHECKGLERROR
7321                 switch(vid.renderpath)
7322                 {
7323                 case RENDERPATH_GL20:
7324                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7325                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7326                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7327                         break;
7328                 case RENDERPATH_CGGL:
7329 #ifdef SUPPORTCG
7330                         CHECKCGERROR
7331                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
7332                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
7333                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7334 #endif
7335                         break;
7336                 case RENDERPATH_GL13:
7337                 case RENDERPATH_GL11:
7338                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7339                         break;
7340                 }
7341         }
7342 }
7343
7344 void R_ResetViewRendering2D(void)
7345 {
7346         r_viewport_t viewport;
7347         DrawQ_Finish();
7348
7349         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7350         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);
7351         R_SetViewport(&viewport);
7352         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7353         GL_Color(1, 1, 1, 1);
7354         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7355         GL_BlendFunc(GL_ONE, GL_ZERO);
7356         GL_AlphaTest(false);
7357         GL_ScissorTest(false);
7358         GL_DepthMask(false);
7359         GL_DepthRange(0, 1);
7360         GL_DepthTest(false);
7361         R_EntityMatrix(&identitymatrix);
7362         R_Mesh_ResetTextureState();
7363         GL_PolygonOffset(0, 0);
7364         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7365         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7366         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7367         qglStencilMask(~0);CHECKGLERROR
7368         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7369         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7370         GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
7371 }
7372
7373 void R_ResetViewRendering3D(void)
7374 {
7375         DrawQ_Finish();
7376
7377         R_SetupView(true);
7378         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7379         GL_Color(1, 1, 1, 1);
7380         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7381         GL_BlendFunc(GL_ONE, GL_ZERO);
7382         GL_AlphaTest(false);
7383         GL_ScissorTest(true);
7384         GL_DepthMask(true);
7385         GL_DepthRange(0, 1);
7386         GL_DepthTest(true);
7387         R_EntityMatrix(&identitymatrix);
7388         R_Mesh_ResetTextureState();
7389         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7390         qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7391         qglDepthFunc(GL_LEQUAL);CHECKGLERROR
7392         qglDisable(GL_STENCIL_TEST);CHECKGLERROR
7393         qglStencilMask(~0);CHECKGLERROR
7394         qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
7395         qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
7396         GL_CullFace(r_refdef.view.cullface_back);
7397 }
7398
7399 /*
7400 ================
7401 R_RenderView_UpdateViewVectors
7402 ================
7403 */
7404 static void R_RenderView_UpdateViewVectors(void)
7405 {
7406         // break apart the view matrix into vectors for various purposes
7407         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
7408         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
7409         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
7410         VectorNegate(r_refdef.view.left, r_refdef.view.right);
7411         // make an inverted copy of the view matrix for tracking sprites
7412         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
7413 }
7414
7415 void R_RenderScene(void);
7416 void R_RenderWaterPlanes(void);
7417
7418 static void R_Water_StartFrame(void)
7419 {
7420         int i;
7421         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
7422         r_waterstate_waterplane_t *p;
7423
7424         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
7425                 return;
7426
7427         switch(vid.renderpath)
7428         {
7429         case RENDERPATH_GL20:
7430         case RENDERPATH_CGGL:
7431                 break;
7432         case RENDERPATH_GL13:
7433         case RENDERPATH_GL11:
7434                 return;
7435         }
7436
7437         // set waterwidth and waterheight to the water resolution that will be
7438         // used (often less than the screen resolution for faster rendering)
7439         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
7440         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
7441
7442         // calculate desired texture sizes
7443         // can't use water if the card does not support the texture size
7444         if (!r_water.integer || r_showsurfaces.integer)
7445                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
7446         else if (vid.support.arb_texture_non_power_of_two)
7447         {
7448                 texturewidth = waterwidth;
7449                 textureheight = waterheight;
7450                 camerawidth = waterwidth;
7451                 cameraheight = waterheight;
7452         }
7453         else
7454         {
7455                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
7456                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
7457                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
7458                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
7459         }
7460
7461         // allocate textures as needed
7462         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
7463         {
7464                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7465                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
7466                 {
7467                         if (p->texture_refraction)
7468                                 R_FreeTexture(p->texture_refraction);
7469                         p->texture_refraction = NULL;
7470                         if (p->texture_reflection)
7471                                 R_FreeTexture(p->texture_reflection);
7472                         p->texture_reflection = NULL;
7473                         if (p->texture_camera)
7474                                 R_FreeTexture(p->texture_camera);
7475                         p->texture_camera = NULL;
7476                 }
7477                 memset(&r_waterstate, 0, sizeof(r_waterstate));
7478                 r_waterstate.texturewidth = texturewidth;
7479                 r_waterstate.textureheight = textureheight;
7480                 r_waterstate.camerawidth = camerawidth;
7481                 r_waterstate.cameraheight = cameraheight;
7482         }
7483
7484         if (r_waterstate.texturewidth)
7485         {
7486                 r_waterstate.enabled = true;
7487
7488                 // when doing a reduced render (HDR) we want to use a smaller area
7489                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
7490                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
7491
7492                 // set up variables that will be used in shader setup
7493                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7494                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7495                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
7496                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
7497         }
7498
7499         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
7500         r_waterstate.numwaterplanes = 0;
7501 }
7502
7503 void R_Water_AddWaterPlane(msurface_t *surface)
7504 {
7505         int triangleindex, planeindex;
7506         const int *e;
7507         vec3_t vert[3];
7508         vec3_t normal;
7509         vec3_t center;
7510         mplane_t plane;
7511         int cam_ent;
7512         r_waterstate_waterplane_t *p;
7513         texture_t *t = R_GetCurrentTexture(surface->texture);
7514         cam_ent = t->camera_entity;
7515         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
7516                 cam_ent = 0;
7517
7518         // just use the first triangle with a valid normal for any decisions
7519         VectorClear(normal);
7520         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
7521         {
7522                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
7523                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
7524                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
7525                 TriangleNormal(vert[0], vert[1], vert[2], normal);
7526                 if (VectorLength2(normal) >= 0.001)
7527                         break;
7528         }
7529
7530         VectorCopy(normal, plane.normal);
7531         VectorNormalize(plane.normal);
7532         plane.dist = DotProduct(vert[0], plane.normal);
7533         PlaneClassify(&plane);
7534         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
7535         {
7536                 // skip backfaces (except if nocullface is set)
7537                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
7538                         return;
7539                 VectorNegate(plane.normal, plane.normal);
7540                 plane.dist *= -1;
7541                 PlaneClassify(&plane);
7542         }
7543
7544
7545         // find a matching plane if there is one
7546         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7547                 if(p->camera_entity == t->camera_entity)
7548                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
7549                                 break;
7550         if (planeindex >= r_waterstate.maxwaterplanes)
7551                 return; // nothing we can do, out of planes
7552
7553         // if this triangle does not fit any known plane rendered this frame, add one
7554         if (planeindex >= r_waterstate.numwaterplanes)
7555         {
7556                 // store the new plane
7557                 r_waterstate.numwaterplanes++;
7558                 p->plane = plane;
7559                 // clear materialflags and pvs
7560                 p->materialflags = 0;
7561                 p->pvsvalid = false;
7562                 p->camera_entity = t->camera_entity;
7563         }
7564         // merge this surface's materialflags into the waterplane
7565         p->materialflags |= t->currentmaterialflags;
7566         if(!(p->materialflags & MATERIALFLAG_CAMERA))
7567         {
7568                 // merge this surface's PVS into the waterplane
7569                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
7570                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
7571                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
7572                 {
7573                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
7574                         p->pvsvalid = true;
7575                 }
7576         }
7577 }
7578
7579 static void R_Water_ProcessPlanes(void)
7580 {
7581         r_refdef_view_t originalview;
7582         r_refdef_view_t myview;
7583         int planeindex;
7584         r_waterstate_waterplane_t *p;
7585         vec3_t visorigin;
7586
7587         originalview = r_refdef.view;
7588
7589         // make sure enough textures are allocated
7590         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7591         {
7592                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7593                 {
7594                         if (!p->texture_refraction)
7595                                 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, -1, NULL);
7596                         if (!p->texture_refraction)
7597                                 goto error;
7598                 }
7599                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7600                 {
7601                         if (!p->texture_camera)
7602                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR, -1, NULL);
7603                         if (!p->texture_camera)
7604                                 goto error;
7605                 }
7606
7607                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7608                 {
7609                         if (!p->texture_reflection)
7610                                 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, -1, NULL);
7611                         if (!p->texture_reflection)
7612                                 goto error;
7613                 }
7614         }
7615
7616         // render views
7617         r_refdef.view = originalview;
7618         r_refdef.view.showdebug = false;
7619         r_refdef.view.width = r_waterstate.waterwidth;
7620         r_refdef.view.height = r_waterstate.waterheight;
7621         r_refdef.view.useclipplane = true;
7622         myview = r_refdef.view;
7623         r_waterstate.renderingscene = true;
7624         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
7625         {
7626                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
7627                 {
7628                         r_refdef.view = myview;
7629                         // render reflected scene and copy into texture
7630                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
7631                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
7632                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
7633                         r_refdef.view.clipplane = p->plane;
7634                         // reverse the cullface settings for this render
7635                         r_refdef.view.cullface_front = GL_FRONT;
7636                         r_refdef.view.cullface_back = GL_BACK;
7637                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
7638                         {
7639                                 r_refdef.view.usecustompvs = true;
7640                                 if (p->pvsvalid)
7641                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7642                                 else
7643                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
7644                         }
7645
7646                         R_ResetViewRendering3D();
7647                         R_ClearScreen(r_refdef.fogenabled);
7648                         R_View_Update();
7649                         R_RenderScene();
7650
7651                         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);
7652                 }
7653
7654                 // render the normal view scene and copy into texture
7655                 // (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)
7656                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
7657                 {
7658                         r_waterstate.renderingrefraction = true;
7659                         r_refdef.view = myview;
7660
7661                         r_refdef.view.clipplane = p->plane;
7662                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7663                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7664
7665                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
7666                         {
7667                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7668                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
7669                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7670                                 R_RenderView_UpdateViewVectors();
7671                                 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);
7672                         }
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_refraction, 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                 else if (p->materialflags & MATERIALFLAG_CAMERA)
7685                 {
7686                         r_refdef.view = myview;
7687
7688                         r_refdef.view.clipplane = p->plane;
7689                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
7690                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
7691
7692                         r_refdef.view.width = r_waterstate.camerawidth;
7693                         r_refdef.view.height = r_waterstate.cameraheight;
7694                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
7695                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
7696
7697                         if(p->camera_entity)
7698                         {
7699                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
7700                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
7701                         }
7702
7703                         // reverse the cullface settings for this render
7704                         r_refdef.view.cullface_front = GL_FRONT;
7705                         r_refdef.view.cullface_back = GL_BACK;
7706                         // also reverse the view matrix
7707                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
7708                         R_RenderView_UpdateViewVectors();
7709                         if(p->camera_entity)
7710                                 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);
7711                         
7712                         // camera needs no clipplane
7713                         r_refdef.view.useclipplane = false;
7714
7715                         PlaneClassify(&r_refdef.view.clipplane);
7716
7717                         R_ResetViewRendering3D();
7718                         R_ClearScreen(r_refdef.fogenabled);
7719                         R_View_Update();
7720                         R_RenderScene();
7721
7722                         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);
7723                         r_waterstate.renderingrefraction = false;
7724                 }
7725
7726         }
7727         r_waterstate.renderingscene = false;
7728         r_refdef.view = originalview;
7729         R_ResetViewRendering3D();
7730         R_ClearScreen(r_refdef.fogenabled);
7731         R_View_Update();
7732         return;
7733 error:
7734         r_refdef.view = originalview;
7735         r_waterstate.renderingscene = false;
7736         Cvar_SetValueQuick(&r_water, 0);
7737         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
7738         return;
7739 }
7740
7741 void R_Bloom_StartFrame(void)
7742 {
7743         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
7744
7745         switch(vid.renderpath)
7746         {
7747         case RENDERPATH_GL20:
7748         case RENDERPATH_CGGL:
7749                 break;
7750         case RENDERPATH_GL13:
7751         case RENDERPATH_GL11:
7752                 return;
7753         }
7754
7755         // set bloomwidth and bloomheight to the bloom resolution that will be
7756         // used (often less than the screen resolution for faster rendering)
7757         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
7758         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
7759         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
7760         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
7761         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
7762
7763         // calculate desired texture sizes
7764         if (vid.support.arb_texture_non_power_of_two)
7765         {
7766                 screentexturewidth = r_refdef.view.width;
7767                 screentextureheight = r_refdef.view.height;
7768                 bloomtexturewidth = r_bloomstate.bloomwidth;
7769                 bloomtextureheight = r_bloomstate.bloomheight;
7770         }
7771         else
7772         {
7773                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
7774                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
7775                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
7776                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
7777         }
7778
7779         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))
7780         {
7781                 Cvar_SetValueQuick(&r_hdr, 0);
7782                 Cvar_SetValueQuick(&r_bloom, 0);
7783                 Cvar_SetValueQuick(&r_motionblur, 0);
7784                 Cvar_SetValueQuick(&r_damageblur, 0);
7785         }
7786
7787         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)))
7788                 screentexturewidth = screentextureheight = 0;
7789         if (!r_hdr.integer && !r_bloom.integer)
7790                 bloomtexturewidth = bloomtextureheight = 0;
7791
7792         // allocate textures as needed
7793         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
7794         {
7795                 if (r_bloomstate.texture_screen)
7796                         R_FreeTexture(r_bloomstate.texture_screen);
7797                 r_bloomstate.texture_screen = NULL;
7798                 r_bloomstate.screentexturewidth = screentexturewidth;
7799                 r_bloomstate.screentextureheight = screentextureheight;
7800                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
7801                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
7802         }
7803         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
7804         {
7805                 if (r_bloomstate.texture_bloom)
7806                         R_FreeTexture(r_bloomstate.texture_bloom);
7807                 r_bloomstate.texture_bloom = NULL;
7808                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
7809                 r_bloomstate.bloomtextureheight = bloomtextureheight;
7810                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
7811                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7812         }
7813
7814         // when doing a reduced render (HDR) we want to use a smaller area
7815         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
7816         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
7817         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
7818         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
7819         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
7820
7821         // set up a texcoord array for the full resolution screen image
7822         // (we have to keep this around to copy back during final render)
7823         r_bloomstate.screentexcoord2f[0] = 0;
7824         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7825         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7826         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
7827         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
7828         r_bloomstate.screentexcoord2f[5] = 0;
7829         r_bloomstate.screentexcoord2f[6] = 0;
7830         r_bloomstate.screentexcoord2f[7] = 0;
7831
7832         // set up a texcoord array for the reduced resolution bloom image
7833         // (which will be additive blended over the screen image)
7834         r_bloomstate.bloomtexcoord2f[0] = 0;
7835         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7836         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7837         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7838         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
7839         r_bloomstate.bloomtexcoord2f[5] = 0;
7840         r_bloomstate.bloomtexcoord2f[6] = 0;
7841         r_bloomstate.bloomtexcoord2f[7] = 0;
7842
7843         if (r_hdr.integer || r_bloom.integer)
7844         {
7845                 r_bloomstate.enabled = true;
7846                 r_bloomstate.hdr = r_hdr.integer != 0;
7847         }
7848
7849         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);
7850 }
7851
7852 void R_Bloom_CopyBloomTexture(float colorscale)
7853 {
7854         r_refdef.stats.bloom++;
7855
7856         // scale down screen texture to the bloom texture size
7857         CHECKGLERROR
7858         R_SetViewport(&r_bloomstate.viewport);
7859         GL_BlendFunc(GL_ONE, GL_ZERO);
7860         GL_Color(colorscale, colorscale, colorscale, 1);
7861         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
7862         // TODO: do boxfilter scale-down in shader?
7863         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
7864         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7865         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7866
7867         // we now have a bloom image in the framebuffer
7868         // copy it into the bloom image texture for later processing
7869         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);
7870         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7871 }
7872
7873 void R_Bloom_CopyHDRTexture(void)
7874 {
7875         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);
7876         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
7877 }
7878
7879 void R_Bloom_MakeTexture(void)
7880 {
7881         int x, range, dir;
7882         float xoffset, yoffset, r, brighten;
7883
7884         r_refdef.stats.bloom++;
7885
7886         R_ResetViewRendering2D();
7887
7888         // we have a bloom image in the framebuffer
7889         CHECKGLERROR
7890         R_SetViewport(&r_bloomstate.viewport);
7891
7892         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
7893         {
7894                 x *= 2;
7895                 r = bound(0, r_bloom_colorexponent.value / x, 1);
7896                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
7897                 GL_Color(r,r,r,1);
7898                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7899                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7900                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7901                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7902
7903                 // copy the vertically blurred bloom view to a texture
7904                 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);
7905                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7906         }
7907
7908         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
7909         brighten = r_bloom_brighten.value;
7910         if (r_hdr.integer)
7911                 brighten *= r_hdr_range.value;
7912         brighten = sqrt(brighten);
7913         if(range >= 1)
7914                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
7915         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7916
7917         for (dir = 0;dir < 2;dir++)
7918         {
7919                 // blend on at multiple vertical offsets to achieve a vertical blur
7920                 // TODO: do offset blends using GLSL
7921                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
7922                 GL_BlendFunc(GL_ONE, GL_ZERO);
7923                 for (x = -range;x <= range;x++)
7924                 {
7925                         if (!dir){xoffset = 0;yoffset = x;}
7926                         else {xoffset = x;yoffset = 0;}
7927                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
7928                         yoffset /= (float)r_bloomstate.bloomtextureheight;
7929                         // compute a texcoord array with the specified x and y offset
7930                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
7931                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7932                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7933                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
7934                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
7935                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
7936                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
7937                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
7938                         // this r value looks like a 'dot' particle, fading sharply to
7939                         // black at the edges
7940                         // (probably not realistic but looks good enough)
7941                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
7942                         //r = brighten/(range*2+1);
7943                         r = brighten / (range * 2 + 1);
7944                         if(range >= 1)
7945                                 r *= (1 - x*x/(float)(range*range));
7946                         GL_Color(r, r, r, 1);
7947                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
7948                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7949                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7950                         GL_BlendFunc(GL_ONE, GL_ONE);
7951                 }
7952
7953                 // copy the vertically blurred bloom view to a texture
7954                 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);
7955                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7956         }
7957
7958         // apply subtract last
7959         // (just like it would be in a GLSL shader)
7960         if (r_bloom_colorsubtract.value > 0 && vid.support.ext_blend_subtract)
7961         {
7962                 GL_BlendFunc(GL_ONE, GL_ZERO);
7963                 GL_Color(1,1,1,1);
7964                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7965                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
7966                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7967                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7968
7969                 GL_BlendFunc(GL_ONE, GL_ONE);
7970                 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT);
7971                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7972                 GL_Color(r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 1);
7973                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
7974                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7975                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
7976                 qglBlendEquationEXT(GL_FUNC_ADD_EXT);
7977
7978                 // copy the darkened bloom view to a texture
7979                 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);
7980                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
7981         }
7982 }
7983
7984 void R_HDR_RenderBloomTexture(void)
7985 {
7986         int oldwidth, oldheight;
7987         float oldcolorscale;
7988
7989         oldcolorscale = r_refdef.view.colorscale;
7990         oldwidth = r_refdef.view.width;
7991         oldheight = r_refdef.view.height;
7992         r_refdef.view.width = r_bloomstate.bloomwidth;
7993         r_refdef.view.height = r_bloomstate.bloomheight;
7994
7995         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
7996         // TODO: add exposure compensation features
7997         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
7998
7999         r_refdef.view.showdebug = false;
8000         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8001
8002         R_ResetViewRendering3D();
8003
8004         R_ClearScreen(r_refdef.fogenabled);
8005         if (r_timereport_active)
8006                 R_TimeReport("HDRclear");
8007
8008         R_View_Update();
8009         if (r_timereport_active)
8010                 R_TimeReport("visibility");
8011
8012         // only do secondary renders with HDR if r_hdr is 2 or higher
8013         r_waterstate.numwaterplanes = 0;
8014         if (r_waterstate.enabled && r_hdr.integer >= 2)
8015                 R_RenderWaterPlanes();
8016
8017         r_refdef.view.showdebug = true;
8018         R_RenderScene();
8019         r_waterstate.numwaterplanes = 0;
8020
8021         R_ResetViewRendering2D();
8022
8023         R_Bloom_CopyHDRTexture();
8024         R_Bloom_MakeTexture();
8025
8026         // restore the view settings
8027         r_refdef.view.width = oldwidth;
8028         r_refdef.view.height = oldheight;
8029         r_refdef.view.colorscale = oldcolorscale;
8030
8031         R_ResetViewRendering3D();
8032
8033         R_ClearScreen(r_refdef.fogenabled);
8034         if (r_timereport_active)
8035                 R_TimeReport("viewclear");
8036 }
8037
8038 static void R_BlendView(void)
8039 {
8040         unsigned int permutation;
8041         float uservecs[4][4];
8042
8043         switch (vid.renderpath)
8044         {
8045         case RENDERPATH_GL20:
8046         case RENDERPATH_CGGL:
8047                 permutation =
8048                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8049                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8050                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8051                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8052                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8053
8054                 if (r_bloomstate.texture_screen)
8055                 {
8056                         // make sure the buffer is available
8057                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8058
8059                         R_ResetViewRendering2D();
8060
8061                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8062                         {
8063                                 // declare variables
8064                                 float speed;
8065                                 static float avgspeed;
8066
8067                                 speed = VectorLength(cl.movement_velocity);
8068
8069                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8070                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8071
8072                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8073                                 speed = bound(0, speed, 1);
8074                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8075
8076                                 // calculate values into a standard alpha
8077                                 cl.motionbluralpha = 1 - exp(-
8078                                                 (
8079                                                  (r_motionblur.value * speed / 80)
8080                                                  +
8081                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8082                                                 )
8083                                                 /
8084                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8085                                            );
8086
8087                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8088                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8089                                 // apply the blur
8090                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8091                                 {
8092                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8093                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8094                                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8095                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8096                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8097                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8098                                 }
8099                         }
8100
8101                         // copy view into the screen texture
8102                         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);
8103                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8104                 }
8105                 else if (!r_bloomstate.texture_bloom)
8106                 {
8107                         // we may still have to do view tint...
8108                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8109                         {
8110                                 // apply a color tint to the whole view
8111                                 R_ResetViewRendering2D();
8112                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8113                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8114                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8115                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8116                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8117                         }
8118                         break; // no screen processing, no bloom, skip it
8119                 }
8120
8121                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8122                 {
8123                         // render simple bloom effect
8124                         // copy the screen and shrink it and darken it for the bloom process
8125                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8126                         // make the bloom texture
8127                         R_Bloom_MakeTexture();
8128                 }
8129
8130 #if _MSC_VER >= 1400
8131 #define sscanf sscanf_s
8132 #endif
8133                 memset(uservecs, 0, sizeof(uservecs));
8134                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8135                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8136                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8137                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8138
8139                 R_ResetViewRendering2D();
8140                 GL_Color(1, 1, 1, 1);
8141                 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8142                 GL_BlendFunc(GL_ONE, GL_ZERO);
8143
8144                 switch(vid.renderpath)
8145                 {
8146                 case RENDERPATH_GL20:
8147                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8148                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8149                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8150                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8151                         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]);
8152                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8153                         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]);
8154                         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]);
8155                         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]);
8156                         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]);
8157                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8158                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8159                         break;
8160                 case RENDERPATH_CGGL:
8161 #ifdef SUPPORTCG
8162                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
8163                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
8164                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
8165                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
8166                         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
8167                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
8168                         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
8169                         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
8170                         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
8171                         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
8172                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
8173                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
8174 #endif
8175                         break;
8176                 default:
8177                         break;
8178                 }
8179                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8180                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8181                 break;
8182         case RENDERPATH_GL13:
8183         case RENDERPATH_GL11:
8184                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8185                 {
8186                         // apply a color tint to the whole view
8187                         R_ResetViewRendering2D();
8188                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8189                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8190                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8191                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8192                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8193                 }
8194                 break;
8195         }
8196 }
8197
8198 matrix4x4_t r_waterscrollmatrix;
8199
8200 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8201 {
8202         if (r_refdef.fog_density)
8203         {
8204                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8205                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8206                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8207
8208                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8209                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8210                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8211                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8212
8213                 {
8214                         vec3_t fogvec;
8215                         VectorCopy(r_refdef.fogcolor, fogvec);
8216                         //   color.rgb *= ContrastBoost * SceneBrightness;
8217                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8218                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8219                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8220                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8221                 }
8222         }
8223 }
8224
8225 void R_UpdateVariables(void)
8226 {
8227         R_Textures_Frame();
8228
8229         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8230
8231         r_refdef.farclip = r_farclip_base.value;
8232         if (r_refdef.scene.worldmodel)
8233                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8234         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8235
8236         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8237                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8238         r_refdef.polygonfactor = 0;
8239         r_refdef.polygonoffset = 0;
8240         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8241         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8242
8243         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8244         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8245         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
8246         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8247         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8248         if (r_showsurfaces.integer)
8249         {
8250                 r_refdef.scene.rtworld = false;
8251                 r_refdef.scene.rtworldshadows = false;
8252                 r_refdef.scene.rtdlight = false;
8253                 r_refdef.scene.rtdlightshadows = false;
8254                 r_refdef.lightmapintensity = 0;
8255         }
8256
8257         if (gamemode == GAME_NEHAHRA)
8258         {
8259                 if (gl_fogenable.integer)
8260                 {
8261                         r_refdef.oldgl_fogenable = true;
8262                         r_refdef.fog_density = gl_fogdensity.value;
8263                         r_refdef.fog_red = gl_fogred.value;
8264                         r_refdef.fog_green = gl_foggreen.value;
8265                         r_refdef.fog_blue = gl_fogblue.value;
8266                         r_refdef.fog_alpha = 1;
8267                         r_refdef.fog_start = 0;
8268                         r_refdef.fog_end = gl_skyclip.value;
8269                         r_refdef.fog_height = 1<<30;
8270                         r_refdef.fog_fadedepth = 128;
8271                 }
8272                 else if (r_refdef.oldgl_fogenable)
8273                 {
8274                         r_refdef.oldgl_fogenable = false;
8275                         r_refdef.fog_density = 0;
8276                         r_refdef.fog_red = 0;
8277                         r_refdef.fog_green = 0;
8278                         r_refdef.fog_blue = 0;
8279                         r_refdef.fog_alpha = 0;
8280                         r_refdef.fog_start = 0;
8281                         r_refdef.fog_end = 0;
8282                         r_refdef.fog_height = 1<<30;
8283                         r_refdef.fog_fadedepth = 128;
8284                 }
8285         }
8286
8287         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
8288         r_refdef.fog_start = max(0, r_refdef.fog_start);
8289         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
8290
8291         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
8292
8293         if (r_refdef.fog_density && r_drawfog.integer)
8294         {
8295                 r_refdef.fogenabled = true;
8296                 // this is the point where the fog reaches 0.9986 alpha, which we
8297                 // consider a good enough cutoff point for the texture
8298                 // (0.9986 * 256 == 255.6)
8299                 if (r_fog_exp2.integer)
8300                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
8301                 else
8302                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
8303                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
8304                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
8305                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
8306                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
8307                         R_BuildFogHeightTexture();
8308                 // fog color was already set
8309                 // update the fog texture
8310                 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)
8311                         R_BuildFogTexture();
8312                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
8313                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
8314         }
8315         else
8316                 r_refdef.fogenabled = false;
8317
8318         switch(vid.renderpath)
8319         {
8320         case RENDERPATH_GL20:
8321         case RENDERPATH_CGGL:
8322                 if(v_glslgamma.integer && !vid_gammatables_trivial)
8323                 {
8324                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
8325                         {
8326                                 // build GLSL gamma texture
8327 #define RAMPWIDTH 256
8328                                 unsigned short ramp[RAMPWIDTH * 3];
8329                                 unsigned char rampbgr[RAMPWIDTH][4];
8330                                 int i;
8331
8332                                 r_texture_gammaramps_serial = vid_gammatables_serial;
8333
8334                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
8335                                 for(i = 0; i < RAMPWIDTH; ++i)
8336                                 {
8337                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8338                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
8339                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
8340                                         rampbgr[i][3] = 0;
8341                                 }
8342                                 if (r_texture_gammaramps)
8343                                 {
8344                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
8345                                 }
8346                                 else
8347                                 {
8348                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT | TEXF_ALLOWUPDATES, -1, NULL);
8349                                 }
8350                         }
8351                 }
8352                 else
8353                 {
8354                         // remove GLSL gamma texture
8355                 }
8356                 break;
8357         case RENDERPATH_GL13:
8358         case RENDERPATH_GL11:
8359                 break;
8360         }
8361 }
8362
8363 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
8364 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
8365 /*
8366 ================
8367 R_SelectScene
8368 ================
8369 */
8370 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
8371         if( scenetype != r_currentscenetype ) {
8372                 // store the old scenetype
8373                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
8374                 r_currentscenetype = scenetype;
8375                 // move in the new scene
8376                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
8377         }
8378 }
8379
8380 /*
8381 ================
8382 R_GetScenePointer
8383 ================
8384 */
8385 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
8386 {
8387         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
8388         if( scenetype == r_currentscenetype ) {
8389                 return &r_refdef.scene;
8390         } else {
8391                 return &r_scenes_store[ scenetype ];
8392         }
8393 }
8394
8395 /*
8396 ================
8397 R_RenderView
8398 ================
8399 */
8400 void R_RenderView(void)
8401 {
8402         if (r_timereport_active)
8403                 R_TimeReport("start");
8404         r_textureframe++; // used only by R_GetCurrentTexture
8405         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
8406
8407         if (!r_drawentities.integer)
8408                 r_refdef.scene.numentities = 0;
8409
8410         R_AnimCache_ClearCache();
8411         R_FrameData_NewFrame();
8412
8413         if (r_refdef.view.isoverlay)
8414         {
8415                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
8416                 GL_Clear( GL_DEPTH_BUFFER_BIT );
8417                 R_TimeReport("depthclear");
8418
8419                 r_refdef.view.showdebug = false;
8420
8421                 r_waterstate.enabled = false;
8422                 r_waterstate.numwaterplanes = 0;
8423
8424                 R_RenderScene();
8425
8426                 CHECKGLERROR
8427                 return;
8428         }
8429
8430         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
8431                 return; //Host_Error ("R_RenderView: NULL worldmodel");
8432
8433         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
8434
8435         R_RenderView_UpdateViewVectors();
8436
8437         R_Shadow_UpdateWorldLightSelection();
8438
8439         R_Bloom_StartFrame();
8440         R_Water_StartFrame();
8441
8442         CHECKGLERROR
8443         if (r_timereport_active)
8444                 R_TimeReport("viewsetup");
8445
8446         R_ResetViewRendering3D();
8447
8448         if (r_refdef.view.clear || r_refdef.fogenabled)
8449         {
8450                 R_ClearScreen(r_refdef.fogenabled);
8451                 if (r_timereport_active)
8452                         R_TimeReport("viewclear");
8453         }
8454         r_refdef.view.clear = true;
8455
8456         // this produces a bloom texture to be used in R_BlendView() later
8457         if (r_hdr.integer && r_bloomstate.bloomwidth)
8458         {
8459                 R_HDR_RenderBloomTexture();
8460                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
8461                 r_textureframe++; // used only by R_GetCurrentTexture
8462         }
8463
8464         r_refdef.view.showdebug = true;
8465
8466         R_View_Update();
8467         if (r_timereport_active)
8468                 R_TimeReport("visibility");
8469
8470         r_waterstate.numwaterplanes = 0;
8471         if (r_waterstate.enabled)
8472                 R_RenderWaterPlanes();
8473
8474         R_RenderScene();
8475         r_waterstate.numwaterplanes = 0;
8476
8477         R_BlendView();
8478         if (r_timereport_active)
8479                 R_TimeReport("blendview");
8480
8481         GL_Scissor(0, 0, vid.width, vid.height);
8482         GL_ScissorTest(false);
8483         CHECKGLERROR
8484 }
8485
8486 void R_RenderWaterPlanes(void)
8487 {
8488         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
8489         {
8490                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
8491                 if (r_timereport_active)
8492                         R_TimeReport("waterworld");
8493         }
8494
8495         // don't let sound skip if going slow
8496         if (r_refdef.scene.extraupdate)
8497                 S_ExtraUpdate ();
8498
8499         R_DrawModelsAddWaterPlanes();
8500         if (r_timereport_active)
8501                 R_TimeReport("watermodels");
8502
8503         if (r_waterstate.numwaterplanes)
8504         {
8505                 R_Water_ProcessPlanes();
8506                 if (r_timereport_active)
8507                         R_TimeReport("waterscenes");
8508         }
8509 }
8510
8511 extern void R_DrawLightningBeams (void);
8512 extern void VM_CL_AddPolygonsToMeshQueue (void);
8513 extern void R_DrawPortals (void);
8514 extern cvar_t cl_locs_show;
8515 static void R_DrawLocs(void);
8516 static void R_DrawEntityBBoxes(void);
8517 static void R_DrawModelDecals(void);
8518 extern void R_DrawModelShadows(void);
8519 extern void R_DrawModelShadowMaps(void);
8520 extern cvar_t cl_decals_newsystem;
8521 extern qboolean r_shadow_usingdeferredprepass;
8522 void R_RenderScene(void)
8523 {
8524         qboolean shadowmapping = false;
8525
8526         if (r_timereport_active)
8527                 R_TimeReport("beginscene");
8528
8529         r_refdef.stats.renders++;
8530
8531         R_UpdateFogColor();
8532
8533         // don't let sound skip if going slow
8534         if (r_refdef.scene.extraupdate)
8535                 S_ExtraUpdate ();
8536
8537         R_MeshQueue_BeginScene();
8538
8539         R_SkyStartFrame();
8540
8541         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);
8542
8543         if (r_timereport_active)
8544                 R_TimeReport("skystartframe");
8545
8546         if (cl.csqc_vidvars.drawworld)
8547         {
8548                 // don't let sound skip if going slow
8549                 if (r_refdef.scene.extraupdate)
8550                         S_ExtraUpdate ();
8551
8552                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
8553                 {
8554                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
8555                         if (r_timereport_active)
8556                                 R_TimeReport("worldsky");
8557                 }
8558
8559                 if (R_DrawBrushModelsSky() && r_timereport_active)
8560                         R_TimeReport("bmodelsky");
8561
8562                 if (skyrendermasked && skyrenderlater)
8563                 {
8564                         // we have to force off the water clipping plane while rendering sky
8565                         R_SetupView(false);
8566                         R_Sky();
8567                         R_SetupView(true);
8568                         if (r_timereport_active)
8569                                 R_TimeReport("sky");
8570                 }
8571         }
8572
8573         R_AnimCache_CacheVisibleEntities();
8574         if (r_timereport_active)
8575                 R_TimeReport("animation");
8576
8577         R_Shadow_PrepareLights();
8578         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
8579                 R_Shadow_PrepareModelShadows();
8580         if (r_timereport_active)
8581                 R_TimeReport("preparelights");
8582
8583         if (R_Shadow_ShadowMappingEnabled())
8584                 shadowmapping = true;
8585
8586         if (r_shadow_usingdeferredprepass)
8587                 R_Shadow_DrawPrepass();
8588
8589         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
8590         {
8591                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
8592                 if (r_timereport_active)
8593                         R_TimeReport("worlddepth");
8594         }
8595         if (r_depthfirst.integer >= 2)
8596         {
8597                 R_DrawModelsDepth();
8598                 if (r_timereport_active)
8599                         R_TimeReport("modeldepth");
8600         }
8601
8602         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
8603         {
8604                 R_DrawModelShadowMaps();
8605                 R_ResetViewRendering3D();
8606                 // don't let sound skip if going slow
8607                 if (r_refdef.scene.extraupdate)
8608                         S_ExtraUpdate ();
8609         }
8610
8611         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
8612         {
8613                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
8614                 if (r_timereport_active)
8615                         R_TimeReport("world");
8616         }
8617
8618         // don't let sound skip if going slow
8619         if (r_refdef.scene.extraupdate)
8620                 S_ExtraUpdate ();
8621
8622         R_DrawModels();
8623         if (r_timereport_active)
8624                 R_TimeReport("models");
8625
8626         // don't let sound skip if going slow
8627         if (r_refdef.scene.extraupdate)
8628                 S_ExtraUpdate ();
8629
8630         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8631         {
8632                 R_DrawModelShadows();
8633                 R_ResetViewRendering3D();
8634                 // don't let sound skip if going slow
8635                 if (r_refdef.scene.extraupdate)
8636                         S_ExtraUpdate ();
8637         }
8638
8639         if (!r_shadow_usingdeferredprepass)
8640         {
8641                 R_Shadow_DrawLights();
8642                 if (r_timereport_active)
8643                         R_TimeReport("rtlights");
8644         }
8645
8646         // don't let sound skip if going slow
8647         if (r_refdef.scene.extraupdate)
8648                 S_ExtraUpdate ();
8649
8650         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
8651         {
8652                 R_DrawModelShadows();
8653                 R_ResetViewRendering3D();
8654                 // don't let sound skip if going slow
8655                 if (r_refdef.scene.extraupdate)
8656                         S_ExtraUpdate ();
8657         }
8658
8659         if (cl.csqc_vidvars.drawworld)
8660         {
8661                 if (cl_decals_newsystem.integer)
8662                 {
8663                         R_DrawModelDecals();
8664                         if (r_timereport_active)
8665                                 R_TimeReport("modeldecals");
8666                 }
8667                 else
8668                 {
8669                         R_DrawDecals();
8670                         if (r_timereport_active)
8671                                 R_TimeReport("decals");
8672                 }
8673
8674                 R_DrawParticles();
8675                 if (r_timereport_active)
8676                         R_TimeReport("particles");
8677
8678                 R_DrawExplosions();
8679                 if (r_timereport_active)
8680                         R_TimeReport("explosions");
8681
8682                 R_DrawLightningBeams();
8683                 if (r_timereport_active)
8684                         R_TimeReport("lightning");
8685         }
8686
8687         VM_CL_AddPolygonsToMeshQueue();
8688
8689         if (r_refdef.view.showdebug)
8690         {
8691                 if (cl_locs_show.integer)
8692                 {
8693                         R_DrawLocs();
8694                         if (r_timereport_active)
8695                                 R_TimeReport("showlocs");
8696                 }
8697
8698                 if (r_drawportals.integer)
8699                 {
8700                         R_DrawPortals();
8701                         if (r_timereport_active)
8702                                 R_TimeReport("portals");
8703                 }
8704
8705                 if (r_showbboxes.value > 0)
8706                 {
8707                         R_DrawEntityBBoxes();
8708                         if (r_timereport_active)
8709                                 R_TimeReport("bboxes");
8710                 }
8711         }
8712
8713         R_MeshQueue_RenderTransparent();
8714         if (r_timereport_active)
8715                 R_TimeReport("drawtrans");
8716
8717         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))
8718         {
8719                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
8720                 if (r_timereport_active)
8721                         R_TimeReport("worlddebug");
8722                 R_DrawModelsDebug();
8723                 if (r_timereport_active)
8724                         R_TimeReport("modeldebug");
8725         }
8726
8727         if (cl.csqc_vidvars.drawworld)
8728         {
8729                 R_Shadow_DrawCoronas();
8730                 if (r_timereport_active)
8731                         R_TimeReport("coronas");
8732         }
8733
8734         // don't let sound skip if going slow
8735         if (r_refdef.scene.extraupdate)
8736                 S_ExtraUpdate ();
8737
8738         R_ResetViewRendering2D();
8739 }
8740
8741 static const unsigned short bboxelements[36] =
8742 {
8743         5, 1, 3, 5, 3, 7,
8744         6, 2, 0, 6, 0, 4,
8745         7, 3, 2, 7, 2, 6,
8746         4, 0, 1, 4, 1, 5,
8747         4, 5, 7, 4, 7, 6,
8748         1, 0, 2, 1, 2, 3,
8749 };
8750
8751 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
8752 {
8753         int i;
8754         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
8755
8756         RSurf_ActiveWorldEntity();
8757
8758         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8759         GL_DepthMask(false);
8760         GL_DepthRange(0, 1);
8761         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8762         R_Mesh_ResetTextureState();
8763
8764         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
8765         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
8766         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
8767         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
8768         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
8769         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
8770         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
8771         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
8772         R_FillColors(color4f, 8, cr, cg, cb, ca);
8773         if (r_refdef.fogenabled)
8774         {
8775                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
8776                 {
8777                         f1 = RSurf_FogVertex(v);
8778                         f2 = 1 - f1;
8779                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
8780                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
8781                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
8782                 }
8783         }
8784         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
8785         R_Mesh_ResetTextureState();
8786         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8787         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
8788 }
8789
8790 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8791 {
8792         int i;
8793         float color[4];
8794         prvm_edict_t *edict;
8795         prvm_prog_t *prog_save = prog;
8796
8797         // this function draws bounding boxes of server entities
8798         if (!sv.active)
8799                 return;
8800
8801         GL_CullFace(GL_NONE);
8802         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8803
8804         prog = 0;
8805         SV_VM_Begin();
8806         for (i = 0;i < numsurfaces;i++)
8807         {
8808                 edict = PRVM_EDICT_NUM(surfacelist[i]);
8809                 switch ((int)edict->fields.server->solid)
8810                 {
8811                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
8812                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
8813                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
8814                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
8815                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
8816                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
8817                 }
8818                 color[3] *= r_showbboxes.value;
8819                 color[3] = bound(0, color[3], 1);
8820                 GL_DepthTest(!r_showdisabledepthtest.integer);
8821                 GL_CullFace(r_refdef.view.cullface_front);
8822                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
8823         }
8824         SV_VM_End();
8825         prog = prog_save;
8826 }
8827
8828 static void R_DrawEntityBBoxes(void)
8829 {
8830         int i;
8831         prvm_edict_t *edict;
8832         vec3_t center;
8833         prvm_prog_t *prog_save = prog;
8834
8835         // this function draws bounding boxes of server entities
8836         if (!sv.active)
8837                 return;
8838
8839         prog = 0;
8840         SV_VM_Begin();
8841         for (i = 0;i < prog->num_edicts;i++)
8842         {
8843                 edict = PRVM_EDICT_NUM(i);
8844                 if (edict->priv.server->free)
8845                         continue;
8846                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
8847                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
8848                         continue;
8849                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
8850                         continue;
8851                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
8852                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
8853         }
8854         SV_VM_End();
8855         prog = prog_save;
8856 }
8857
8858 static const int nomodelelement3i[24] =
8859 {
8860         5, 2, 0,
8861         5, 1, 2,
8862         5, 0, 3,
8863         5, 3, 1,
8864         0, 2, 4,
8865         2, 1, 4,
8866         3, 0, 4,
8867         1, 3, 4
8868 };
8869
8870 static const unsigned short nomodelelement3s[24] =
8871 {
8872         5, 2, 0,
8873         5, 1, 2,
8874         5, 0, 3,
8875         5, 3, 1,
8876         0, 2, 4,
8877         2, 1, 4,
8878         3, 0, 4,
8879         1, 3, 4
8880 };
8881
8882 static const float nomodelvertex3f[6*3] =
8883 {
8884         -16,   0,   0,
8885          16,   0,   0,
8886           0, -16,   0,
8887           0,  16,   0,
8888           0,   0, -16,
8889           0,   0,  16
8890 };
8891
8892 static const float nomodelcolor4f[6*4] =
8893 {
8894         0.0f, 0.0f, 0.5f, 1.0f,
8895         0.0f, 0.0f, 0.5f, 1.0f,
8896         0.0f, 0.5f, 0.0f, 1.0f,
8897         0.0f, 0.5f, 0.0f, 1.0f,
8898         0.5f, 0.0f, 0.0f, 1.0f,
8899         0.5f, 0.0f, 0.0f, 1.0f
8900 };
8901
8902 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
8903 {
8904         int i;
8905         float f1, f2, *c;
8906         float color4f[6*4];
8907
8908         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);
8909
8910         // this is only called once per entity so numsurfaces is always 1, and
8911         // surfacelist is always {0}, so this code does not handle batches
8912
8913         if (rsurface.ent_flags & RENDER_ADDITIVE)
8914         {
8915                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
8916                 GL_DepthMask(false);
8917         }
8918         else if (rsurface.colormod[3] < 1)
8919         {
8920                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8921                 GL_DepthMask(false);
8922         }
8923         else
8924         {
8925                 GL_BlendFunc(GL_ONE, GL_ZERO);
8926                 GL_DepthMask(true);
8927         }
8928         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
8929         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
8930         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
8931         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
8932         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8933         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
8934         for (i = 0, c = color4f;i < 6;i++, c += 4)
8935         {
8936                 c[0] *= rsurface.colormod[0];
8937                 c[1] *= rsurface.colormod[1];
8938                 c[2] *= rsurface.colormod[2];
8939                 c[3] *= rsurface.colormod[3];
8940         }
8941         if (r_refdef.fogenabled)
8942         {
8943                 for (i = 0, c = color4f;i < 6;i++, c += 4)
8944                 {
8945                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
8946                         f2 = 1 - f1;
8947                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
8948                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
8949                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
8950                 }
8951         }
8952         R_Mesh_ResetTextureState();
8953         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8954         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8955 }
8956
8957 void R_DrawNoModel(entity_render_t *ent)
8958 {
8959         vec3_t org;
8960         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8961         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8962                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8963         else
8964                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8965 }
8966
8967 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
8968 {
8969         vec3_t right1, right2, diff, normal;
8970
8971         VectorSubtract (org2, org1, normal);
8972
8973         // calculate 'right' vector for start
8974         VectorSubtract (r_refdef.view.origin, org1, diff);
8975         CrossProduct (normal, diff, right1);
8976         VectorNormalize (right1);
8977
8978         // calculate 'right' vector for end
8979         VectorSubtract (r_refdef.view.origin, org2, diff);
8980         CrossProduct (normal, diff, right2);
8981         VectorNormalize (right2);
8982
8983         vert[ 0] = org1[0] + width * right1[0];
8984         vert[ 1] = org1[1] + width * right1[1];
8985         vert[ 2] = org1[2] + width * right1[2];
8986         vert[ 3] = org1[0] - width * right1[0];
8987         vert[ 4] = org1[1] - width * right1[1];
8988         vert[ 5] = org1[2] - width * right1[2];
8989         vert[ 6] = org2[0] - width * right2[0];
8990         vert[ 7] = org2[1] - width * right2[1];
8991         vert[ 8] = org2[2] - width * right2[2];
8992         vert[ 9] = org2[0] + width * right2[0];
8993         vert[10] = org2[1] + width * right2[1];
8994         vert[11] = org2[2] + width * right2[2];
8995 }
8996
8997 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)
8998 {
8999         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9000         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9001         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9002         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9003         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9004         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9005         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9006         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9007         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9008         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9009         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9010         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9011 }
9012
9013 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9014 {
9015         int i;
9016         float *vertex3f;
9017         float v[3];
9018         VectorSet(v, x, y, z);
9019         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9020                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9021                         break;
9022         if (i == mesh->numvertices)
9023         {
9024                 if (mesh->numvertices < mesh->maxvertices)
9025                 {
9026                         VectorCopy(v, vertex3f);
9027                         mesh->numvertices++;
9028                 }
9029                 return mesh->numvertices;
9030         }
9031         else
9032                 return i;
9033 }
9034
9035 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9036 {
9037         int i;
9038         int *e, element[3];
9039         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9040         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9041         e = mesh->element3i + mesh->numtriangles * 3;
9042         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9043         {
9044                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9045                 if (mesh->numtriangles < mesh->maxtriangles)
9046                 {
9047                         *e++ = element[0];
9048                         *e++ = element[1];
9049                         *e++ = element[2];
9050                         mesh->numtriangles++;
9051                 }
9052                 element[1] = element[2];
9053         }
9054 }
9055
9056 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9057 {
9058         int i;
9059         int *e, element[3];
9060         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9061         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9062         e = mesh->element3i + mesh->numtriangles * 3;
9063         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9064         {
9065                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9066                 if (mesh->numtriangles < mesh->maxtriangles)
9067                 {
9068                         *e++ = element[0];
9069                         *e++ = element[1];
9070                         *e++ = element[2];
9071                         mesh->numtriangles++;
9072                 }
9073                 element[1] = element[2];
9074         }
9075 }
9076
9077 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9078 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9079 {
9080         int planenum, planenum2;
9081         int w;
9082         int tempnumpoints;
9083         mplane_t *plane, *plane2;
9084         double maxdist;
9085         double temppoints[2][256*3];
9086         // figure out how large a bounding box we need to properly compute this brush
9087         maxdist = 0;
9088         for (w = 0;w < numplanes;w++)
9089                 maxdist = max(maxdist, fabs(planes[w].dist));
9090         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9091         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9092         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9093         {
9094                 w = 0;
9095                 tempnumpoints = 4;
9096                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9097                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9098                 {
9099                         if (planenum2 == planenum)
9100                                 continue;
9101                         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);
9102                         w = !w;
9103                 }
9104                 if (tempnumpoints < 3)
9105                         continue;
9106                 // generate elements forming a triangle fan for this polygon
9107                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9108         }
9109 }
9110
9111 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)
9112 {
9113         texturelayer_t *layer;
9114         layer = t->currentlayers + t->currentnumlayers++;
9115         layer->type = type;
9116         layer->depthmask = depthmask;
9117         layer->blendfunc1 = blendfunc1;
9118         layer->blendfunc2 = blendfunc2;
9119         layer->texture = texture;
9120         layer->texmatrix = *matrix;
9121         layer->color[0] = r;
9122         layer->color[1] = g;
9123         layer->color[2] = b;
9124         layer->color[3] = a;
9125 }
9126
9127 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9128 {
9129         if(parms[0] == 0 && parms[1] == 0)
9130                 return false;
9131         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9132                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9133                         return false;
9134         return true;
9135 }
9136
9137 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9138 {
9139         double index, f;
9140         index = parms[2] + r_refdef.scene.time * parms[3];
9141         index -= floor(index);
9142         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9143         {
9144         default:
9145         case Q3WAVEFUNC_NONE:
9146         case Q3WAVEFUNC_NOISE:
9147         case Q3WAVEFUNC_COUNT:
9148                 f = 0;
9149                 break;
9150         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9151         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9152         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9153         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9154         case Q3WAVEFUNC_TRIANGLE:
9155                 index *= 4;
9156                 f = index - floor(index);
9157                 if (index < 1)
9158                         f = f;
9159                 else if (index < 2)
9160                         f = 1 - f;
9161                 else if (index < 3)
9162                         f = -f;
9163                 else
9164                         f = -(1 - f);
9165                 break;
9166         }
9167         f = parms[0] + parms[1] * f;
9168         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9169                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9170         return (float) f;
9171 }
9172
9173 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9174 {
9175         int w, h, idx;
9176         float f;
9177         float tcmat[12];
9178         matrix4x4_t matrix, temp;
9179         switch(tcmod->tcmod)
9180         {
9181                 case Q3TCMOD_COUNT:
9182                 case Q3TCMOD_NONE:
9183                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9184                                 matrix = r_waterscrollmatrix;
9185                         else
9186                                 matrix = identitymatrix;
9187                         break;
9188                 case Q3TCMOD_ENTITYTRANSLATE:
9189                         // this is used in Q3 to allow the gamecode to control texcoord
9190                         // scrolling on the entity, which is not supported in darkplaces yet.
9191                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9192                         break;
9193                 case Q3TCMOD_ROTATE:
9194                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9195                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9196                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9197                         break;
9198                 case Q3TCMOD_SCALE:
9199                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9200                         break;
9201                 case Q3TCMOD_SCROLL:
9202                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9203                         break;
9204                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9205                         w = (int) tcmod->parms[0];
9206                         h = (int) tcmod->parms[1];
9207                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9208                         f = f - floor(f);
9209                         idx = (int) floor(f * w * h);
9210                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9211                         break;
9212                 case Q3TCMOD_STRETCH:
9213                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
9214                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
9215                         break;
9216                 case Q3TCMOD_TRANSFORM:
9217                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
9218                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
9219                         VectorSet(tcmat +  6, 0                   , 0                , 1);
9220                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
9221                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
9222                         break;
9223                 case Q3TCMOD_TURBULENT:
9224                         // this is handled in the RSurf_PrepareVertices function
9225                         matrix = identitymatrix;
9226                         break;
9227         }
9228         temp = *texmatrix;
9229         Matrix4x4_Concat(texmatrix, &matrix, &temp);
9230 }
9231
9232 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
9233 {
9234         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
9235         char name[MAX_QPATH];
9236         skinframe_t *skinframe;
9237         unsigned char pixels[296*194];
9238         strlcpy(cache->name, skinname, sizeof(cache->name));
9239         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
9240         if (developer_loading.integer)
9241                 Con_Printf("loading %s\n", name);
9242         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
9243         if (!skinframe || !skinframe->base)
9244         {
9245                 unsigned char *f;
9246                 fs_offset_t filesize;
9247                 skinframe = NULL;
9248                 f = FS_LoadFile(name, tempmempool, true, &filesize);
9249                 if (f)
9250                 {
9251                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
9252                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
9253                         Mem_Free(f);
9254                 }
9255         }
9256         cache->skinframe = skinframe;
9257 }
9258
9259 texture_t *R_GetCurrentTexture(texture_t *t)
9260 {
9261         int i;
9262         const entity_render_t *ent = rsurface.entity;
9263         dp_model_t *model = ent->model;
9264         q3shaderinfo_layer_tcmod_t *tcmod;
9265
9266         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
9267                 return t->currentframe;
9268         t->update_lastrenderframe = r_textureframe;
9269         t->update_lastrenderentity = (void *)ent;
9270
9271         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
9272                 t->camera_entity = ent->entitynumber;
9273         else
9274                 t->camera_entity = 0;
9275
9276         // switch to an alternate material if this is a q1bsp animated material
9277         {
9278                 texture_t *texture = t;
9279                 int s = rsurface.ent_skinnum;
9280                 if ((unsigned int)s >= (unsigned int)model->numskins)
9281                         s = 0;
9282                 if (model->skinscenes)
9283                 {
9284                         if (model->skinscenes[s].framecount > 1)
9285                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
9286                         else
9287                                 s = model->skinscenes[s].firstframe;
9288                 }
9289                 if (s > 0)
9290                         t = t + s * model->num_surfaces;
9291                 if (t->animated)
9292                 {
9293                         // use an alternate animation if the entity's frame is not 0,
9294                         // and only if the texture has an alternate animation
9295                         if (rsurface.ent_alttextures && t->anim_total[1])
9296                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
9297                         else
9298                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
9299                 }
9300                 texture->currentframe = t;
9301         }
9302
9303         // update currentskinframe to be a qw skin or animation frame
9304         if (rsurface.ent_qwskin >= 0)
9305         {
9306                 i = rsurface.ent_qwskin;
9307                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
9308                 {
9309                         r_qwskincache_size = cl.maxclients;
9310                         if (r_qwskincache)
9311                                 Mem_Free(r_qwskincache);
9312                         r_qwskincache = Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
9313                 }
9314                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
9315                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
9316                 t->currentskinframe = r_qwskincache[i].skinframe;
9317                 if (t->currentskinframe == NULL)
9318                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9319         }
9320         else if (t->numskinframes >= 2)
9321                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
9322         if (t->backgroundnumskinframes >= 2)
9323                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
9324
9325         t->currentmaterialflags = t->basematerialflags;
9326         t->currentalpha = rsurface.colormod[3];
9327         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
9328                 t->currentalpha *= r_wateralpha.value;
9329         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
9330                 t->currentalpha *= t->r_water_wateralpha;
9331         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
9332                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
9333         if (!(rsurface.ent_flags & RENDER_LIGHT))
9334                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
9335         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
9336         {
9337                 // pick a model lighting mode
9338                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
9339                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
9340                 else
9341                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
9342         }
9343         if (rsurface.ent_flags & RENDER_ADDITIVE)
9344                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9345         else if (t->currentalpha < 1)
9346                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
9347         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
9348                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
9349         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
9350                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
9351         if (t->backgroundnumskinframes)
9352                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
9353         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
9354         {
9355                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
9356                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
9357         }
9358         else
9359                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
9360         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
9361                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
9362
9363         // there is no tcmod
9364         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9365         {
9366                 t->currenttexmatrix = r_waterscrollmatrix;
9367                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
9368         }
9369         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
9370         {
9371                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
9372                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
9373         }
9374
9375         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9376                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
9377         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
9378                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
9379
9380         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
9381         if (t->currentskinframe->qpixels)
9382                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
9383         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
9384         if (!t->basetexture)
9385                 t->basetexture = r_texture_notexture;
9386         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
9387         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
9388         t->nmaptexture = t->currentskinframe->nmap;
9389         if (!t->nmaptexture)
9390                 t->nmaptexture = r_texture_blanknormalmap;
9391         t->glosstexture = r_texture_black;
9392         t->glowtexture = t->currentskinframe->glow;
9393         t->fogtexture = t->currentskinframe->fog;
9394         t->reflectmasktexture = t->currentskinframe->reflect;
9395         if (t->backgroundnumskinframes)
9396         {
9397                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
9398                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
9399                 t->backgroundglosstexture = r_texture_black;
9400                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
9401                 if (!t->backgroundnmaptexture)
9402                         t->backgroundnmaptexture = r_texture_blanknormalmap;
9403         }
9404         else
9405         {
9406                 t->backgroundbasetexture = r_texture_white;
9407                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9408                 t->backgroundglosstexture = r_texture_black;
9409                 t->backgroundglowtexture = NULL;
9410         }
9411         t->specularpower = r_shadow_glossexponent.value;
9412         // TODO: store reference values for these in the texture?
9413         t->specularscale = 0;
9414         if (r_shadow_gloss.integer > 0)
9415         {
9416                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
9417                 {
9418                         if (r_shadow_glossintensity.value > 0)
9419                         {
9420                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
9421                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
9422                                 t->specularscale = r_shadow_glossintensity.value;
9423                         }
9424                 }
9425                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
9426                 {
9427                         t->glosstexture = r_texture_white;
9428                         t->backgroundglosstexture = r_texture_white;
9429                         t->specularscale = r_shadow_gloss2intensity.value;
9430                         t->specularpower = r_shadow_gloss2exponent.value;
9431                 }
9432         }
9433         t->specularscale *= t->specularscalemod;
9434         t->specularpower *= t->specularpowermod;
9435
9436         // lightmaps mode looks bad with dlights using actual texturing, so turn
9437         // off the colormap and glossmap, but leave the normalmap on as it still
9438         // accurately represents the shading involved
9439         if (gl_lightmaps.integer)
9440         {
9441                 t->basetexture = r_texture_grey128;
9442                 t->pantstexture = r_texture_black;
9443                 t->shirttexture = r_texture_black;
9444                 t->nmaptexture = r_texture_blanknormalmap;
9445                 t->glosstexture = r_texture_black;
9446                 t->glowtexture = NULL;
9447                 t->fogtexture = NULL;
9448                 t->reflectmasktexture = NULL;
9449                 t->backgroundbasetexture = NULL;
9450                 t->backgroundnmaptexture = r_texture_blanknormalmap;
9451                 t->backgroundglosstexture = r_texture_black;
9452                 t->backgroundglowtexture = NULL;
9453                 t->specularscale = 0;
9454                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
9455         }
9456
9457         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
9458         VectorClear(t->dlightcolor);
9459         t->currentnumlayers = 0;
9460         if (t->currentmaterialflags & MATERIALFLAG_WALL)
9461         {
9462                 int blendfunc1, blendfunc2;
9463                 qboolean depthmask;
9464                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
9465                 {
9466                         blendfunc1 = GL_SRC_ALPHA;
9467                         blendfunc2 = GL_ONE;
9468                 }
9469                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
9470                 {
9471                         blendfunc1 = GL_SRC_ALPHA;
9472                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
9473                 }
9474                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9475                 {
9476                         blendfunc1 = t->customblendfunc[0];
9477                         blendfunc2 = t->customblendfunc[1];
9478                 }
9479                 else
9480                 {
9481                         blendfunc1 = GL_ONE;
9482                         blendfunc2 = GL_ZERO;
9483                 }
9484                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
9485                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9486                 {
9487                         // fullbright is not affected by r_refdef.lightmapintensity
9488                         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]);
9489                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9490                                 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]);
9491                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9492                                 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]);
9493                 }
9494                 else
9495                 {
9496                         vec3_t ambientcolor;
9497                         float colorscale;
9498                         // set the color tint used for lights affecting this surface
9499                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
9500                         colorscale = 2;
9501                         // q3bsp has no lightmap updates, so the lightstylevalue that
9502                         // would normally be baked into the lightmap must be
9503                         // applied to the color
9504                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
9505                         if (model->type == mod_brushq3)
9506                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
9507                         colorscale *= r_refdef.lightmapintensity;
9508                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
9509                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
9510                         // basic lit geometry
9511                         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]);
9512                         // add pants/shirt if needed
9513                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9514                                 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]);
9515                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9516                                 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]);
9517                         // now add ambient passes if needed
9518                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
9519                         {
9520                                 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]);
9521                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
9522                                         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]);
9523                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
9524                                         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]);
9525                         }
9526                 }
9527                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
9528                         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]);
9529                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
9530                 {
9531                         // if this is opaque use alpha blend which will darken the earlier
9532                         // passes cheaply.
9533                         //
9534                         // if this is an alpha blended material, all the earlier passes
9535                         // were darkened by fog already, so we only need to add the fog
9536                         // color ontop through the fog mask texture
9537                         //
9538                         // if this is an additive blended material, all the earlier passes
9539                         // were darkened by fog already, and we should not add fog color
9540                         // (because the background was not darkened, there is no fog color
9541                         // that was lost behind it).
9542                         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]);
9543                 }
9544         }
9545
9546         return t->currentframe;
9547 }
9548
9549 rsurfacestate_t rsurface;
9550
9551 void R_Mesh_ResizeArrays(int newvertices)
9552 {
9553         unsigned char *base;
9554         size_t size;
9555         if (rsurface.array_size >= newvertices)
9556                 return;
9557         if (rsurface.array_base)
9558                 Mem_Free(rsurface.array_base);
9559         rsurface.array_size = (newvertices + 1023) & ~1023;
9560         size = 0;
9561         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9562         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9563         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9564         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9565         size += rsurface.array_size * sizeof(float[3]);
9566         size += rsurface.array_size * sizeof(float[3]);
9567         size += rsurface.array_size * sizeof(float[3]);
9568         size += rsurface.array_size * sizeof(float[3]);
9569         size += rsurface.array_size * sizeof(float[3]);
9570         size += rsurface.array_size * sizeof(float[3]);
9571         size += rsurface.array_size * sizeof(float[3]);
9572         size += rsurface.array_size * sizeof(float[3]);
9573         size += rsurface.array_size * sizeof(float[4]);
9574         size += rsurface.array_size * sizeof(float[2]);
9575         size += rsurface.array_size * sizeof(float[2]);
9576         size += rsurface.array_size * sizeof(float[4]);
9577         size += rsurface.array_size * sizeof(int[3]);
9578         size += rsurface.array_size * sizeof(unsigned short[3]);
9579         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
9580         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
9581         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
9582         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
9583         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
9584         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9585         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9586         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9587         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9588         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9589         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9590         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9591         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
9592         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9593         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9594         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
9595         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
9596         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
9597         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
9598 }
9599
9600 void RSurf_ActiveWorldEntity(void)
9601 {
9602         dp_model_t *model = r_refdef.scene.worldmodel;
9603         //if (rsurface.entity == r_refdef.scene.worldentity)
9604         //      return;
9605         rsurface.entity = r_refdef.scene.worldentity;
9606         rsurface.skeleton = NULL;
9607         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
9608         rsurface.ent_skinnum = 0;
9609         rsurface.ent_qwskin = -1;
9610         rsurface.ent_shadertime = 0;
9611         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
9612         if (rsurface.array_size < model->surfmesh.num_vertices)
9613                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9614         rsurface.matrix = identitymatrix;
9615         rsurface.inversematrix = identitymatrix;
9616         rsurface.matrixscale = 1;
9617         rsurface.inversematrixscale = 1;
9618         R_EntityMatrix(&identitymatrix);
9619         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
9620         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
9621         rsurface.fograngerecip = r_refdef.fograngerecip;
9622         rsurface.fogheightfade = r_refdef.fogheightfade;
9623         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
9624         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9625         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9626         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9627         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9628         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9629         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9630         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
9631         rsurface.colormod[3] = 1;
9632         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);
9633         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9634         rsurface.frameblend[0].lerp = 1;
9635         rsurface.ent_alttextures = false;
9636         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9637         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9638         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9639         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9640         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9641         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9642         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9643         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9644         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9645         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9646         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9647         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9648         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9649         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9650         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9651         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9652         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9653         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9654         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9655         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9656         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9657         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9658         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9659         rsurface.modelelement3i = model->surfmesh.data_element3i;
9660         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9661         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9662         rsurface.modelelement3s = model->surfmesh.data_element3s;
9663         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9664         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9665         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9666         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9667         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9668         rsurface.modelsurfaces = model->data_surfaces;
9669         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9670         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9671         rsurface.modelvertexposition = model->surfmesh.vertexposition;
9672         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9673         rsurface.modelgeneratedvertex = false;
9674         rsurface.batchgeneratedvertex = false;
9675         rsurface.batchfirstvertex = 0;
9676         rsurface.batchnumvertices = 0;
9677         rsurface.batchfirsttriangle = 0;
9678         rsurface.batchnumtriangles = 0;
9679         rsurface.batchvertex3f  = NULL;
9680         rsurface.batchvertex3f_vertexbuffer = NULL;
9681         rsurface.batchvertex3f_bufferoffset = 0;
9682         rsurface.batchsvector3f = NULL;
9683         rsurface.batchsvector3f_vertexbuffer = NULL;
9684         rsurface.batchsvector3f_bufferoffset = 0;
9685         rsurface.batchtvector3f = NULL;
9686         rsurface.batchtvector3f_vertexbuffer = NULL;
9687         rsurface.batchtvector3f_bufferoffset = 0;
9688         rsurface.batchnormal3f  = NULL;
9689         rsurface.batchnormal3f_vertexbuffer = NULL;
9690         rsurface.batchnormal3f_bufferoffset = 0;
9691         rsurface.batchlightmapcolor4f = NULL;
9692         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9693         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9694         rsurface.batchtexcoordtexture2f = NULL;
9695         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9696         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9697         rsurface.batchtexcoordlightmap2f = NULL;
9698         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9699         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9700         rsurface.batchvertexmesh = NULL;
9701         rsurface.batchvertexmeshbuffer = NULL;
9702         rsurface.batchvertexposition = NULL;
9703         rsurface.batchvertexpositionbuffer = NULL;
9704         rsurface.batchelement3i = NULL;
9705         rsurface.batchelement3i_indexbuffer = NULL;
9706         rsurface.batchelement3i_bufferoffset = 0;
9707         rsurface.batchelement3s = NULL;
9708         rsurface.batchelement3s_indexbuffer = NULL;
9709         rsurface.batchelement3s_bufferoffset = 0;
9710         rsurface.passcolor4f = NULL;
9711         rsurface.passcolor4f_vertexbuffer = NULL;
9712         rsurface.passcolor4f_bufferoffset = 0;
9713 }
9714
9715 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
9716 {
9717         dp_model_t *model = ent->model;
9718         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
9719         //      return;
9720         rsurface.entity = (entity_render_t *)ent;
9721         rsurface.skeleton = ent->skeleton;
9722         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
9723         rsurface.ent_skinnum = ent->skinnum;
9724         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;
9725         rsurface.ent_shadertime = ent->shadertime;
9726         rsurface.ent_flags = ent->flags;
9727         if (rsurface.array_size < model->surfmesh.num_vertices)
9728                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
9729         rsurface.matrix = ent->matrix;
9730         rsurface.inversematrix = ent->inversematrix;
9731         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9732         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9733         R_EntityMatrix(&rsurface.matrix);
9734         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9735         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9736         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9737         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9738         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9739         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9740         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
9741         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
9742         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
9743         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
9744         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
9745         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
9746         rsurface.colormod[3] = ent->alpha;
9747         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
9748         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
9749         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
9750         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9751         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9752         if (ent->model->brush.submodel && !prepass)
9753         {
9754                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
9755                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
9756         }
9757         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
9758         {
9759                 if (ent->animcache_vertex3f && !r_framedata_failed)
9760                 {
9761                         rsurface.modelvertex3f = ent->animcache_vertex3f;
9762                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
9763                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
9764                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
9765                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
9766                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
9767                         rsurface.modelvertexposition = ent->animcache_vertexposition;
9768                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
9769                 }
9770                 else if (wanttangents)
9771                 {
9772                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9773                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
9774                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
9775                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9776                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
9777                         rsurface.modelvertexmesh = NULL;
9778                         rsurface.modelvertexmeshbuffer = NULL;
9779                         rsurface.modelvertexposition = NULL;
9780                         rsurface.modelvertexpositionbuffer = NULL;
9781                 }
9782                 else if (wantnormals)
9783                 {
9784                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9785                         rsurface.modelsvector3f = NULL;
9786                         rsurface.modeltvector3f = NULL;
9787                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
9788                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
9789                         rsurface.modelvertexmesh = NULL;
9790                         rsurface.modelvertexmeshbuffer = NULL;
9791                         rsurface.modelvertexposition = NULL;
9792                         rsurface.modelvertexpositionbuffer = NULL;
9793                 }
9794                 else
9795                 {
9796                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
9797                         rsurface.modelsvector3f = NULL;
9798                         rsurface.modeltvector3f = NULL;
9799                         rsurface.modelnormal3f = NULL;
9800                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
9801                         rsurface.modelvertexmesh = NULL;
9802                         rsurface.modelvertexmeshbuffer = NULL;
9803                         rsurface.modelvertexposition = NULL;
9804                         rsurface.modelvertexpositionbuffer = NULL;
9805                 }
9806                 rsurface.modelvertex3f_vertexbuffer = 0;
9807                 rsurface.modelvertex3f_bufferoffset = 0;
9808                 rsurface.modelsvector3f_vertexbuffer = 0;
9809                 rsurface.modelsvector3f_bufferoffset = 0;
9810                 rsurface.modeltvector3f_vertexbuffer = 0;
9811                 rsurface.modeltvector3f_bufferoffset = 0;
9812                 rsurface.modelnormal3f_vertexbuffer = 0;
9813                 rsurface.modelnormal3f_bufferoffset = 0;
9814                 rsurface.modelgeneratedvertex = true;
9815         }
9816         else
9817         {
9818                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
9819                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9820                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
9821                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
9822                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9823                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
9824                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
9825                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9826                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
9827                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
9828                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9829                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
9830                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
9831                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
9832                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
9833                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
9834                 rsurface.modelgeneratedvertex = false;
9835         }
9836         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
9837         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9838         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
9839         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
9840         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9841         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
9842         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
9843         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
9844         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
9845         rsurface.modelelement3i = model->surfmesh.data_element3i;
9846         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
9847         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
9848         rsurface.modelelement3s = model->surfmesh.data_element3s;
9849         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
9850         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
9851         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
9852         rsurface.modelnumvertices = model->surfmesh.num_vertices;
9853         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
9854         rsurface.modelsurfaces = model->data_surfaces;
9855         rsurface.batchgeneratedvertex = false;
9856         rsurface.batchfirstvertex = 0;
9857         rsurface.batchnumvertices = 0;
9858         rsurface.batchfirsttriangle = 0;
9859         rsurface.batchnumtriangles = 0;
9860         rsurface.batchvertex3f  = NULL;
9861         rsurface.batchvertex3f_vertexbuffer = NULL;
9862         rsurface.batchvertex3f_bufferoffset = 0;
9863         rsurface.batchsvector3f = NULL;
9864         rsurface.batchsvector3f_vertexbuffer = NULL;
9865         rsurface.batchsvector3f_bufferoffset = 0;
9866         rsurface.batchtvector3f = NULL;
9867         rsurface.batchtvector3f_vertexbuffer = NULL;
9868         rsurface.batchtvector3f_bufferoffset = 0;
9869         rsurface.batchnormal3f  = NULL;
9870         rsurface.batchnormal3f_vertexbuffer = NULL;
9871         rsurface.batchnormal3f_bufferoffset = 0;
9872         rsurface.batchlightmapcolor4f = NULL;
9873         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9874         rsurface.batchlightmapcolor4f_bufferoffset = 0;
9875         rsurface.batchtexcoordtexture2f = NULL;
9876         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9877         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9878         rsurface.batchtexcoordlightmap2f = NULL;
9879         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9880         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9881         rsurface.batchvertexmesh = NULL;
9882         rsurface.batchvertexmeshbuffer = NULL;
9883         rsurface.batchvertexposition = NULL;
9884         rsurface.batchvertexpositionbuffer = NULL;
9885         rsurface.batchelement3i = NULL;
9886         rsurface.batchelement3i_indexbuffer = NULL;
9887         rsurface.batchelement3i_bufferoffset = 0;
9888         rsurface.batchelement3s = NULL;
9889         rsurface.batchelement3s_indexbuffer = NULL;
9890         rsurface.batchelement3s_bufferoffset = 0;
9891         rsurface.passcolor4f = NULL;
9892         rsurface.passcolor4f_vertexbuffer = NULL;
9893         rsurface.passcolor4f_bufferoffset = 0;
9894 }
9895
9896 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)
9897 {
9898         int i;
9899
9900         rsurface.entity = r_refdef.scene.worldentity;
9901         rsurface.skeleton = NULL;
9902         rsurface.ent_skinnum = 0;
9903         rsurface.ent_qwskin = -1;
9904         rsurface.ent_shadertime = shadertime;
9905         rsurface.ent_flags = entflags;
9906         rsurface.modelnumvertices = numvertices;
9907         rsurface.modelnumtriangles = numtriangles;
9908         if (rsurface.array_size < rsurface.modelnumvertices)
9909                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
9910         rsurface.matrix = *matrix;
9911         rsurface.inversematrix = *inversematrix;
9912         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9913         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9914         R_EntityMatrix(&rsurface.matrix);
9915         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9916         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9917         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9918         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9919         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9920         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9921         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9922         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9923         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9924         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9925         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9926         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9927         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);
9928         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9929         rsurface.frameblend[0].lerp = 1;
9930         rsurface.ent_alttextures = false;
9931         rsurface.basepolygonfactor = r_refdef.polygonfactor;
9932         rsurface.basepolygonoffset = r_refdef.polygonoffset;
9933         if (wanttangents)
9934         {
9935                 rsurface.modelvertex3f = vertex3f;
9936                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
9937                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
9938                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9939         }
9940         else if (wantnormals)
9941         {
9942                 rsurface.modelvertex3f = vertex3f;
9943                 rsurface.modelsvector3f = NULL;
9944                 rsurface.modeltvector3f = NULL;
9945                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
9946         }
9947         else
9948         {
9949                 rsurface.modelvertex3f = vertex3f;
9950                 rsurface.modelsvector3f = NULL;
9951                 rsurface.modeltvector3f = NULL;
9952                 rsurface.modelnormal3f = NULL;
9953         }
9954         rsurface.modelvertexmesh = NULL;
9955         rsurface.modelvertexmeshbuffer = NULL;
9956         rsurface.modelvertexposition = NULL;
9957         rsurface.modelvertexpositionbuffer = NULL;
9958         rsurface.modelvertex3f_vertexbuffer = 0;
9959         rsurface.modelvertex3f_bufferoffset = 0;
9960         rsurface.modelsvector3f_vertexbuffer = 0;
9961         rsurface.modelsvector3f_bufferoffset = 0;
9962         rsurface.modeltvector3f_vertexbuffer = 0;
9963         rsurface.modeltvector3f_bufferoffset = 0;
9964         rsurface.modelnormal3f_vertexbuffer = 0;
9965         rsurface.modelnormal3f_bufferoffset = 0;
9966         rsurface.modelgeneratedvertex = true;
9967         rsurface.modellightmapcolor4f  = color4f;
9968         rsurface.modellightmapcolor4f_vertexbuffer = 0;
9969         rsurface.modellightmapcolor4f_bufferoffset = 0;
9970         rsurface.modeltexcoordtexture2f  = texcoord2f;
9971         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9972         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9973         rsurface.modeltexcoordlightmap2f  = NULL;
9974         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9975         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9976         rsurface.modelelement3i = element3i;
9977         rsurface.modelelement3i_indexbuffer = NULL;
9978         rsurface.modelelement3i_bufferoffset = 0;
9979         rsurface.modelelement3s = element3s;
9980         rsurface.modelelement3s_indexbuffer = NULL;
9981         rsurface.modelelement3s_bufferoffset = 0;
9982         rsurface.modellightmapoffsets = NULL;
9983         rsurface.modelsurfaces = NULL;
9984         rsurface.batchgeneratedvertex = false;
9985         rsurface.batchfirstvertex = 0;
9986         rsurface.batchnumvertices = 0;
9987         rsurface.batchfirsttriangle = 0;
9988         rsurface.batchnumtriangles = 0;
9989         rsurface.batchvertex3f  = NULL;
9990         rsurface.batchvertex3f_vertexbuffer = NULL;
9991         rsurface.batchvertex3f_bufferoffset = 0;
9992         rsurface.batchsvector3f = NULL;
9993         rsurface.batchsvector3f_vertexbuffer = NULL;
9994         rsurface.batchsvector3f_bufferoffset = 0;
9995         rsurface.batchtvector3f = NULL;
9996         rsurface.batchtvector3f_vertexbuffer = NULL;
9997         rsurface.batchtvector3f_bufferoffset = 0;
9998         rsurface.batchnormal3f  = NULL;
9999         rsurface.batchnormal3f_vertexbuffer = NULL;
10000         rsurface.batchnormal3f_bufferoffset = 0;
10001         rsurface.batchlightmapcolor4f = NULL;
10002         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10003         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10004         rsurface.batchtexcoordtexture2f = NULL;
10005         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10006         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10007         rsurface.batchtexcoordlightmap2f = NULL;
10008         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10009         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10010         rsurface.batchvertexmesh = NULL;
10011         rsurface.batchvertexmeshbuffer = NULL;
10012         rsurface.batchvertexposition = NULL;
10013         rsurface.batchvertexpositionbuffer = NULL;
10014         rsurface.batchelement3i = NULL;
10015         rsurface.batchelement3i_indexbuffer = NULL;
10016         rsurface.batchelement3i_bufferoffset = 0;
10017         rsurface.batchelement3s = NULL;
10018         rsurface.batchelement3s_indexbuffer = NULL;
10019         rsurface.batchelement3s_bufferoffset = 0;
10020         rsurface.passcolor4f = NULL;
10021         rsurface.passcolor4f_vertexbuffer = NULL;
10022         rsurface.passcolor4f_bufferoffset = 0;
10023
10024         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10025         {
10026                 if ((wantnormals || wanttangents) && !normal3f)
10027                 {
10028                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10029                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10030                 }
10031                 if (wanttangents && !svector3f)
10032                 {
10033                         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);
10034                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10035                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10036                 }
10037         }
10038
10039         // now convert arrays into vertexmesh structs
10040         for (i = 0;i < numvertices;i++)
10041         {
10042                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10043                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10044                 if (rsurface.modelsvector3f)
10045                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10046                 if (rsurface.modeltvector3f)
10047                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10048                 if (rsurface.modelnormal3f)
10049                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10050                 if (rsurface.modellightmapcolor4f)
10051                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10052                 if (rsurface.modeltexcoordtexture2f)
10053                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10054                 if (rsurface.modeltexcoordlightmap2f)
10055                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10056         }
10057 }
10058
10059 float RSurf_FogPoint(const float *v)
10060 {
10061         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10062         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10063         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10064         float FogHeightFade = r_refdef.fogheightfade;
10065         float fogfrac;
10066         unsigned int fogmasktableindex;
10067         if (r_refdef.fogplaneviewabove)
10068                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10069         else
10070                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10071         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10072         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10073 }
10074
10075 float RSurf_FogVertex(const float *v)
10076 {
10077         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10078         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10079         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10080         float FogHeightFade = rsurface.fogheightfade;
10081         float fogfrac;
10082         unsigned int fogmasktableindex;
10083         if (r_refdef.fogplaneviewabove)
10084                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10085         else
10086                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10087         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10088         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10089 }
10090
10091 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10092 {
10093         int i;
10094         for (i = 0;i < numelements;i++)
10095                 outelement3i[i] = inelement3i[i] + adjust;
10096 }
10097
10098 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10099 extern cvar_t gl_vbo;
10100 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10101 {
10102         int deformindex;
10103         int firsttriangle;
10104         int numtriangles;
10105         int firstvertex;
10106         int endvertex;
10107         int numvertices;
10108         int surfacefirsttriangle;
10109         int surfacenumtriangles;
10110         int surfacefirstvertex;
10111         int surfaceendvertex;
10112         int surfacenumvertices;
10113         int surfaceadjustvertex;
10114         int needsupdate;
10115         int i, j;
10116         qboolean gaps;
10117         qboolean dynamicvertex;
10118         float amplitude;
10119         float animpos;
10120         float scale;
10121         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10122         float waveparms[4];
10123         q3shaderinfo_deform_t *deform;
10124         const msurface_t *surface, *firstsurface;
10125         r_vertexposition_t *vertexposition;
10126         r_vertexmesh_t *vertexmesh;
10127         if (!texturenumsurfaces)
10128                 return;
10129         // find vertex range of this surface batch
10130         gaps = false;
10131         firstsurface = texturesurfacelist[0];
10132         firsttriangle = firstsurface->num_firsttriangle;
10133         numtriangles = 0;
10134         firstvertex = endvertex = firstsurface->num_firstvertex;
10135         for (i = 0;i < texturenumsurfaces;i++)
10136         {
10137                 surface = texturesurfacelist[i];
10138                 if (surface != firstsurface + i)
10139                         gaps = true;
10140                 surfacefirstvertex = surface->num_firstvertex;
10141                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10142                 surfacenumtriangles = surface->num_triangles;
10143                 if (firstvertex > surfacefirstvertex)
10144                         firstvertex = surfacefirstvertex;
10145                 if (endvertex < surfaceendvertex)
10146                         endvertex = surfaceendvertex;
10147                 numtriangles += surfacenumtriangles;
10148         }
10149         if (!numtriangles)
10150                 return;
10151
10152         // we now know the vertex range used, and if there are any gaps in it
10153         rsurface.batchfirstvertex = firstvertex;
10154         rsurface.batchnumvertices = endvertex - firstvertex;
10155         rsurface.batchfirsttriangle = firsttriangle;
10156         rsurface.batchnumtriangles = numtriangles;
10157
10158         // this variable holds flags for which properties have been updated that
10159         // may require regenerating vertexmesh or vertexposition arrays...
10160         needsupdate = 0;
10161
10162         // check if any dynamic vertex processing must occur
10163         dynamicvertex = false;
10164
10165         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10166                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
10167         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10168         {
10169                 switch (deform->deform)
10170                 {
10171                 default:
10172                 case Q3DEFORM_PROJECTIONSHADOW:
10173                 case Q3DEFORM_TEXT0:
10174                 case Q3DEFORM_TEXT1:
10175                 case Q3DEFORM_TEXT2:
10176                 case Q3DEFORM_TEXT3:
10177                 case Q3DEFORM_TEXT4:
10178                 case Q3DEFORM_TEXT5:
10179                 case Q3DEFORM_TEXT6:
10180                 case Q3DEFORM_TEXT7:
10181                 case Q3DEFORM_NONE:
10182                         break;
10183                 case Q3DEFORM_AUTOSPRITE:
10184                         dynamicvertex = true;
10185                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10186                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10187                         break;
10188                 case Q3DEFORM_AUTOSPRITE2:
10189                         dynamicvertex = true;
10190                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10191                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10192                         break;
10193                 case Q3DEFORM_NORMAL:
10194                         dynamicvertex = true;
10195                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10196                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10197                         break;
10198                 case Q3DEFORM_WAVE:
10199                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10200                                 break; // if wavefunc is a nop, ignore this transform
10201                         dynamicvertex = true;
10202                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10203                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10204                         break;
10205                 case Q3DEFORM_BULGE:
10206                         dynamicvertex = true;
10207                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10208                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10209                         break;
10210                 case Q3DEFORM_MOVE:
10211                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10212                                 break; // if wavefunc is a nop, ignore this transform
10213                         dynamicvertex = true;
10214                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10215                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
10216                         break;
10217                 }
10218         }
10219         switch(rsurface.texture->tcgen.tcgen)
10220         {
10221         default:
10222         case Q3TCGEN_TEXTURE:
10223                 break;
10224         case Q3TCGEN_LIGHTMAP:
10225                 dynamicvertex = true;
10226                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10227                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10228                 break;
10229         case Q3TCGEN_VECTOR:
10230                 dynamicvertex = true;
10231                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10232                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10233                 break;
10234         case Q3TCGEN_ENVIRONMENT:
10235                 dynamicvertex = true;
10236                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10237                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10238                 break;
10239         }
10240         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10241         {
10242                 dynamicvertex = true;
10243                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10244                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10245         }
10246
10247         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10248         {
10249                 dynamicvertex = true;
10250                 batchneed |= BATCHNEED_NOGAPS;
10251                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10252         }
10253
10254         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10255         {
10256                 dynamicvertex = true;
10257                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10258                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
10259         }
10260
10261         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10262         {
10263                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10264                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10265                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10266                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10267                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10268                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10269                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10270         }
10271
10272         // when the model data has no vertex buffer (dynamic mesh), we need to
10273         // eliminate gaps
10274         if (!rsurface.modelvertexmeshbuffer || (!gl_vbo.integer && !vid.forcevbo))
10275                 batchneed |= BATCHNEED_NOGAPS;
10276
10277         // if needsupdate, we have to do a dynamic vertex batch for sure
10278         if (needsupdate & batchneed)
10279                 dynamicvertex = true;
10280
10281         // see if we need to build vertexmesh from arrays
10282         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10283                 dynamicvertex = true;
10284
10285         // see if we need to build vertexposition from arrays
10286         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
10287                 dynamicvertex = true;
10288
10289         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10290         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10291                 dynamicvertex = true;
10292
10293         // if there is a chance of animated vertex colors, it's a dynamic batch
10294         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10295                 dynamicvertex = true;
10296
10297         rsurface.batchvertex3f = rsurface.modelvertex3f;
10298         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
10299         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
10300         rsurface.batchsvector3f = rsurface.modelsvector3f;
10301         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
10302         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
10303         rsurface.batchtvector3f = rsurface.modeltvector3f;
10304         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
10305         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
10306         rsurface.batchnormal3f = rsurface.modelnormal3f;
10307         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
10308         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
10309         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
10310         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
10311         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
10312         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
10313         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
10314         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
10315         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
10316         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
10317         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
10318         rsurface.batchvertexposition = rsurface.modelvertexposition;
10319         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
10320         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
10321         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
10322         rsurface.batchelement3i = rsurface.modelelement3i;
10323         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
10324         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
10325         rsurface.batchelement3s = rsurface.modelelement3s;
10326         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
10327         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
10328
10329         // if any dynamic vertex processing has to occur in software, we copy the
10330         // entire surface list together before processing to rebase the vertices
10331         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
10332         //
10333         // if any gaps exist and we do not have a static vertex buffer, we have to
10334         // copy the surface list together to avoid wasting upload bandwidth on the
10335         // vertices in the gaps.
10336         //
10337         // if gaps exist and we have a static vertex buffer, we still have to
10338         // combine the index buffer ranges into one dynamic index buffer.
10339         //
10340         // in all cases we end up with data that can be drawn in one call.
10341
10342         if (!dynamicvertex)
10343         {
10344                 // static vertex data, just set pointers...
10345                 rsurface.batchgeneratedvertex = false;
10346                 // if there are gaps, we want to build a combined index buffer,
10347                 // otherwise use the original static buffer with an appropriate offset
10348                 if (gaps)
10349                 {
10350                         firsttriangle = 0;
10351                         numtriangles = 0;
10352                         for (i = 0;i < texturenumsurfaces;i++)
10353                         {
10354                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10355                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10356                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
10357                                 numtriangles += surfacenumtriangles;
10358                         }
10359                         rsurface.batchelement3i = rsurface.array_batchelement3i;
10360                         rsurface.batchelement3i_indexbuffer = NULL;
10361                         rsurface.batchelement3i_bufferoffset = 0;
10362                         rsurface.batchelement3s = NULL;
10363                         rsurface.batchelement3s_indexbuffer = NULL;
10364                         rsurface.batchelement3s_bufferoffset = 0;
10365                         if (endvertex <= 65536)
10366                         {
10367                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
10368                                 for (i = 0;i < numtriangles*3;i++)
10369                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10370                         }
10371                         rsurface.batchfirsttriangle = firsttriangle;
10372                         rsurface.batchnumtriangles = numtriangles;
10373                 }
10374                 return;
10375         }
10376
10377         // something needs software processing, do it for real...
10378         // we only directly handle interleaved array data in this case...
10379         rsurface.batchgeneratedvertex = true;
10380
10381         // now copy the vertex data into a combined array and make an index array
10382         // (this is what Quake3 does all the time)
10383         //if (gaps || rsurface.batchfirstvertex)
10384         {
10385                 rsurface.batchvertexposition = NULL;
10386                 rsurface.batchvertexpositionbuffer = NULL;
10387                 rsurface.batchvertexmesh = NULL;
10388                 rsurface.batchvertexmeshbuffer = NULL;
10389                 rsurface.batchvertex3f = NULL;
10390                 rsurface.batchvertex3f_vertexbuffer = NULL;
10391                 rsurface.batchvertex3f_bufferoffset = 0;
10392                 rsurface.batchsvector3f = NULL;
10393                 rsurface.batchsvector3f_vertexbuffer = NULL;
10394                 rsurface.batchsvector3f_bufferoffset = 0;
10395                 rsurface.batchtvector3f = NULL;
10396                 rsurface.batchtvector3f_vertexbuffer = NULL;
10397                 rsurface.batchtvector3f_bufferoffset = 0;
10398                 rsurface.batchnormal3f = NULL;
10399                 rsurface.batchnormal3f_vertexbuffer = NULL;
10400                 rsurface.batchnormal3f_bufferoffset = 0;
10401                 rsurface.batchlightmapcolor4f = NULL;
10402                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10403                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10404                 rsurface.batchtexcoordtexture2f = NULL;
10405                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10406                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10407                 rsurface.batchtexcoordlightmap2f = NULL;
10408                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10409                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10410                 rsurface.batchelement3i = rsurface.array_batchelement3i;
10411                 rsurface.batchelement3i_indexbuffer = NULL;
10412                 rsurface.batchelement3i_bufferoffset = 0;
10413                 rsurface.batchelement3s = NULL;
10414                 rsurface.batchelement3s_indexbuffer = NULL;
10415                 rsurface.batchelement3s_bufferoffset = 0;
10416                 // we'll only be setting up certain arrays as needed
10417                 if (batchneed & BATCHNEED_VERTEXPOSITION)
10418                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10419                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10420                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10421                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10422                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10423                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
10424                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10425                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
10426                 {
10427                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10428                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10429                 }
10430                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
10431                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10432                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
10433                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10434                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
10435                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
10436                 numvertices = 0;
10437                 numtriangles = 0;
10438                 for (i = 0;i < texturenumsurfaces;i++)
10439                 {
10440                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
10441                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
10442                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
10443                         surfaceadjustvertex = numvertices - surfacefirstvertex;
10444                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
10445                         // copy only the data requested
10446                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
10447                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
10448                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
10449                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
10450                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
10451                         {
10452                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
10453                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10454                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
10455                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10456                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
10457                                 {
10458                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10459                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
10460                                 }
10461                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
10462                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
10463                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
10464                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10465                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
10466                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
10467                         }
10468                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
10469                         numvertices += surfacenumvertices;
10470                         numtriangles += surfacenumtriangles;
10471                 }
10472
10473                 // generate a 16bit index array as well if possible
10474                 // (in general, dynamic batches fit)
10475                 if (numvertices <= 65536)
10476                 {
10477                         rsurface.batchelement3s = rsurface.array_batchelement3s;
10478                         for (i = 0;i < numtriangles*3;i++)
10479                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
10480                 }
10481
10482                 // since we've copied everything, the batch now starts at 0
10483                 rsurface.batchfirstvertex = 0;
10484                 rsurface.batchnumvertices = numvertices;
10485                 rsurface.batchfirsttriangle = 0;
10486                 rsurface.batchnumtriangles = numtriangles;
10487         }
10488
10489         // q1bsp surfaces rendered in vertex color mode have to have colors
10490         // calculated based on lightstyles
10491         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10492         {
10493                 // generate color arrays for the surfaces in this list
10494                 int c[4];
10495                 int scale;
10496                 int size3;
10497                 const int *offsets;
10498                 const unsigned char *lm;
10499                 numvertices = 0;
10500                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
10501                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10502                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10503                 for (i = 0;i < texturenumsurfaces;i++)
10504                 {
10505                         surface = texturesurfacelist[i];
10506                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10507                         surfacenumvertices = surface->num_vertices;
10508                         if (surface->lightmapinfo->samples)
10509                         {
10510                                 for (j = 0;j < surfacenumvertices;j++)
10511                                 {
10512                                         lm = surface->lightmapinfo->samples + offsets[j];
10513                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10514                                         VectorScale(lm, scale, c);
10515                                         if (surface->lightmapinfo->styles[1] != 255)
10516                                         {
10517                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10518                                                 lm += size3;
10519                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10520                                                 VectorMA(c, scale, lm, c);
10521                                                 if (surface->lightmapinfo->styles[2] != 255)
10522                                                 {
10523                                                         lm += size3;
10524                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10525                                                         VectorMA(c, scale, lm, c);
10526                                                         if (surface->lightmapinfo->styles[3] != 255)
10527                                                         {
10528                                                                 lm += size3;
10529                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10530                                                                 VectorMA(c, scale, lm, c);
10531                                                         }
10532                                                 }
10533                                         }
10534                                         c[0] >>= 15;
10535                                         c[1] >>= 15;
10536                                         c[2] >>= 15;
10537                                         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);
10538                                         numvertices++;
10539                                 }
10540                         }
10541                         else
10542                         {
10543                                 for (j = 0;j < surfacenumvertices;j++)
10544                                 {
10545                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10546                                         numvertices++;
10547                                 }
10548                         }
10549                 }
10550         }
10551
10552         // if vertices are deformed (sprite flares and things in maps, possibly
10553         // water waves, bulges and other deformations), modify the copied vertices
10554         // in place
10555         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10556         {
10557                 switch (deform->deform)
10558                 {
10559                 default:
10560                 case Q3DEFORM_PROJECTIONSHADOW:
10561                 case Q3DEFORM_TEXT0:
10562                 case Q3DEFORM_TEXT1:
10563                 case Q3DEFORM_TEXT2:
10564                 case Q3DEFORM_TEXT3:
10565                 case Q3DEFORM_TEXT4:
10566                 case Q3DEFORM_TEXT5:
10567                 case Q3DEFORM_TEXT6:
10568                 case Q3DEFORM_TEXT7:
10569                 case Q3DEFORM_NONE:
10570                         break;
10571                 case Q3DEFORM_AUTOSPRITE:
10572                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10573                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10574                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10575                         VectorNormalize(newforward);
10576                         VectorNormalize(newright);
10577                         VectorNormalize(newup);
10578                         // a single autosprite surface can contain multiple sprites...
10579                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10580                         {
10581                                 VectorClear(center);
10582                                 for (i = 0;i < 4;i++)
10583                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10584                                 VectorScale(center, 0.25f, center);
10585                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10586                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10587                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10588                                 for (i = 0;i < 4;i++)
10589                                 {
10590                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10591                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
10592                                 }
10593                         }
10594                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10595                         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);
10596                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10597                         rsurface.batchvertex3f_vertexbuffer = NULL;
10598                         rsurface.batchvertex3f_bufferoffset = 0;
10599                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10600                         rsurface.batchsvector3f_vertexbuffer = NULL;
10601                         rsurface.batchsvector3f_bufferoffset = 0;
10602                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10603                         rsurface.batchtvector3f_vertexbuffer = NULL;
10604                         rsurface.batchtvector3f_bufferoffset = 0;
10605                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10606                         rsurface.batchnormal3f_vertexbuffer = NULL;
10607                         rsurface.batchnormal3f_bufferoffset = 0;
10608                         break;
10609                 case Q3DEFORM_AUTOSPRITE2:
10610                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10611                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10612                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10613                         VectorNormalize(newforward);
10614                         VectorNormalize(newright);
10615                         VectorNormalize(newup);
10616                         {
10617                                 const float *v1, *v2;
10618                                 vec3_t start, end;
10619                                 float f, l;
10620                                 struct
10621                                 {
10622                                         float length2;
10623                                         const float *v1;
10624                                         const float *v2;
10625                                 }
10626                                 shortest[2];
10627                                 memset(shortest, 0, sizeof(shortest));
10628                                 // a single autosprite surface can contain multiple sprites...
10629                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
10630                                 {
10631                                         VectorClear(center);
10632                                         for (i = 0;i < 4;i++)
10633                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10634                                         VectorScale(center, 0.25f, center);
10635                                         // find the two shortest edges, then use them to define the
10636                                         // axis vectors for rotating around the central axis
10637                                         for (i = 0;i < 6;i++)
10638                                         {
10639                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10640                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10641                                                 l = VectorDistance2(v1, v2);
10642                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10643                                                 if (v1[2] != v2[2])
10644                                                         l += (1.0f / 1024.0f);
10645                                                 if (shortest[0].length2 > l || i == 0)
10646                                                 {
10647                                                         shortest[1] = shortest[0];
10648                                                         shortest[0].length2 = l;
10649                                                         shortest[0].v1 = v1;
10650                                                         shortest[0].v2 = v2;
10651                                                 }
10652                                                 else if (shortest[1].length2 > l || i == 1)
10653                                                 {
10654                                                         shortest[1].length2 = l;
10655                                                         shortest[1].v1 = v1;
10656                                                         shortest[1].v2 = v2;
10657                                                 }
10658                                         }
10659                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10660                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10661                                         // this calculates the right vector from the shortest edge
10662                                         // and the up vector from the edge midpoints
10663                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10664                                         VectorNormalize(right);
10665                                         VectorSubtract(end, start, up);
10666                                         VectorNormalize(up);
10667                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10668                                         VectorSubtract(rsurface.localvieworigin, center, forward);
10669                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10670                                         VectorNegate(forward, forward);
10671                                         VectorReflect(forward, 0, up, forward);
10672                                         VectorNormalize(forward);
10673                                         CrossProduct(up, forward, newright);
10674                                         VectorNormalize(newright);
10675                                         // rotate the quad around the up axis vector, this is made
10676                                         // especially easy by the fact we know the quad is flat,
10677                                         // so we only have to subtract the center position and
10678                                         // measure distance along the right vector, and then
10679                                         // multiply that by the newright vector and add back the
10680                                         // center position
10681                                         // we also need to subtract the old position to undo the
10682                                         // displacement from the center, which we do with a
10683                                         // DotProduct, the subtraction/addition of center is also
10684                                         // optimized into DotProducts here
10685                                         l = DotProduct(right, center);
10686                                         for (i = 0;i < 4;i++)
10687                                         {
10688                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10689                                                 f = DotProduct(right, v1) - l;
10690                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
10691                                         }
10692                                 }
10693                         }
10694                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10695                         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);
10696                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10697                         rsurface.batchvertex3f_vertexbuffer = NULL;
10698                         rsurface.batchvertex3f_bufferoffset = 0;
10699                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10700                         rsurface.batchsvector3f_vertexbuffer = NULL;
10701                         rsurface.batchsvector3f_bufferoffset = 0;
10702                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10703                         rsurface.batchtvector3f_vertexbuffer = NULL;
10704                         rsurface.batchtvector3f_bufferoffset = 0;
10705                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10706                         rsurface.batchnormal3f_vertexbuffer = NULL;
10707                         rsurface.batchnormal3f_bufferoffset = 0;
10708                         break;
10709                 case Q3DEFORM_NORMAL:
10710                         // deform the normals to make reflections wavey
10711                         for (j = 0;j < rsurface.batchnumvertices;j++)
10712                         {
10713                                 float vertex[3];
10714                                 float *normal = rsurface.array_batchnormal3f + 3*j;
10715                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10716                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
10717                                 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]);
10718                                 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]);
10719                                 VectorNormalize(normal);
10720                         }
10721                         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);
10722                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10723                         rsurface.batchsvector3f_vertexbuffer = NULL;
10724                         rsurface.batchsvector3f_bufferoffset = 0;
10725                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10726                         rsurface.batchtvector3f_vertexbuffer = NULL;
10727                         rsurface.batchtvector3f_bufferoffset = 0;
10728                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10729                         rsurface.batchnormal3f_vertexbuffer = NULL;
10730                         rsurface.batchnormal3f_bufferoffset = 0;
10731                         break;
10732                 case Q3DEFORM_WAVE:
10733                         // deform vertex array to make wavey water and flags and such
10734                         waveparms[0] = deform->waveparms[0];
10735                         waveparms[1] = deform->waveparms[1];
10736                         waveparms[2] = deform->waveparms[2];
10737                         waveparms[3] = deform->waveparms[3];
10738                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10739                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10740                         // this is how a divisor of vertex influence on deformation
10741                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10742                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10743                         for (j = 0;j < rsurface.batchnumvertices;j++)
10744                         {
10745                                 // if the wavefunc depends on time, evaluate it per-vertex
10746                                 if (waveparms[3])
10747                                 {
10748                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10749                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10750                                 }
10751                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10752                         }
10753                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10754                         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);
10755                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10756                         rsurface.batchvertex3f_vertexbuffer = NULL;
10757                         rsurface.batchvertex3f_bufferoffset = 0;
10758                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10759                         rsurface.batchsvector3f_vertexbuffer = NULL;
10760                         rsurface.batchsvector3f_bufferoffset = 0;
10761                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10762                         rsurface.batchtvector3f_vertexbuffer = NULL;
10763                         rsurface.batchtvector3f_bufferoffset = 0;
10764                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10765                         rsurface.batchnormal3f_vertexbuffer = NULL;
10766                         rsurface.batchnormal3f_bufferoffset = 0;
10767                         break;
10768                 case Q3DEFORM_BULGE:
10769                         // deform vertex array to make the surface have moving bulges
10770                         for (j = 0;j < rsurface.batchnumvertices;j++)
10771                         {
10772                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
10773                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
10774                         }
10775                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
10776                         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);
10777                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10778                         rsurface.batchvertex3f_vertexbuffer = NULL;
10779                         rsurface.batchvertex3f_bufferoffset = 0;
10780                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
10781                         rsurface.batchsvector3f_vertexbuffer = NULL;
10782                         rsurface.batchsvector3f_bufferoffset = 0;
10783                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
10784                         rsurface.batchtvector3f_vertexbuffer = NULL;
10785                         rsurface.batchtvector3f_bufferoffset = 0;
10786                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
10787                         rsurface.batchnormal3f_vertexbuffer = NULL;
10788                         rsurface.batchnormal3f_bufferoffset = 0;
10789                         break;
10790                 case Q3DEFORM_MOVE:
10791                         // deform vertex array
10792                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10793                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10794                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10795                         VectorScale(deform->parms, scale, waveparms);
10796                         for (j = 0;j < rsurface.batchnumvertices;j++)
10797                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
10798                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
10799                         rsurface.batchvertex3f_vertexbuffer = NULL;
10800                         rsurface.batchvertex3f_bufferoffset = 0;
10801                         break;
10802                 }
10803         }
10804
10805         // generate texcoords based on the chosen texcoord source
10806         switch(rsurface.texture->tcgen.tcgen)
10807         {
10808         default:
10809         case Q3TCGEN_TEXTURE:
10810                 break;
10811         case Q3TCGEN_LIGHTMAP:
10812                 if (rsurface.batchtexcoordlightmap2f)
10813                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
10814                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10815                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10816                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10817                 break;
10818         case Q3TCGEN_VECTOR:
10819                 for (j = 0;j < rsurface.batchnumvertices;j++)
10820                 {
10821                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10822                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10823                 }
10824                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10825                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10826                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10827                 break;
10828         case Q3TCGEN_ENVIRONMENT:
10829                 // make environment reflections using a spheremap
10830                 for (j = 0;j < rsurface.batchnumvertices;j++)
10831                 {
10832                         // identical to Q3A's method, but executed in worldspace so
10833                         // carried models can be shiny too
10834
10835                         float viewer[3], d, reflected[3], worldreflected[3];
10836
10837                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10838                         // VectorNormalize(viewer);
10839
10840                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10841
10842                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10843                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10844                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10845                         // note: this is proportinal to viewer, so we can normalize later
10846
10847                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10848                         VectorNormalize(worldreflected);
10849
10850                         // note: this sphere map only uses world x and z!
10851                         // so positive and negative y will LOOK THE SAME.
10852                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10853                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10854                 }
10855                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10856                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10857                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10858                 break;
10859         }
10860         // the only tcmod that needs software vertex processing is turbulent, so
10861         // check for it here and apply the changes if needed
10862         // and we only support that as the first one
10863         // (handling a mixture of turbulent and other tcmods would be problematic
10864         //  without punting it entirely to a software path)
10865         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10866         {
10867                 amplitude = rsurface.texture->tcmods[0].parms[1];
10868                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
10869                 for (j = 0;j < rsurface.batchnumvertices;j++)
10870                 {
10871                         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);
10872                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10873                 }
10874                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
10875                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10876                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10877         }
10878
10879         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10880         {
10881                 // convert the modified arrays to vertex structs
10882                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
10883                 rsurface.batchvertexmeshbuffer = NULL;
10884                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10885                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10886                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10887                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10888                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10889                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10890                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10891                 {
10892                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10893                         {
10894                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10895                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10896                         }
10897                 }
10898                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10899                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10900                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
10901                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10902                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10903                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10904                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10905                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
10906                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10907         }
10908
10909         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
10910         {
10911                 // convert the modified arrays to vertex structs
10912                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
10913                 rsurface.batchvertexpositionbuffer = NULL;
10914                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
10915                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
10916                 else
10917                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
10918                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
10919         }
10920 }
10921
10922 void RSurf_DrawBatch(void)
10923 {
10924         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);
10925 }
10926
10927 static void RSurf_BindLightmapForBatch(void)
10928 {
10929         switch(vid.renderpath)
10930         {
10931         case RENDERPATH_CGGL:
10932 #ifdef SUPPORTCG
10933                 if (r_cg_permutation->fp_Texture_Lightmap ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap , rsurface.lightmaptexture );CHECKCGERROR
10934                 if (r_cg_permutation->fp_Texture_Deluxemap) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap, rsurface.deluxemaptexture);CHECKCGERROR
10935 #endif
10936                 break;
10937         case RENDERPATH_GL20:
10938                 if (r_glsl_permutation->loc_Texture_Lightmap  >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture );
10939                 if (r_glsl_permutation->loc_Texture_Deluxemap >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP, rsurface.deluxemaptexture);
10940                 break;
10941         case RENDERPATH_GL13:
10942         case RENDERPATH_GL11:
10943                 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10944                 break;
10945         }
10946 }
10947
10948 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10949 {
10950         // pick the closest matching water plane
10951         int planeindex, vertexindex, bestplaneindex = -1;
10952         float d, bestd;
10953         vec3_t vert;
10954         const float *v;
10955         r_waterstate_waterplane_t *p;
10956         bestd = 0;
10957         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
10958         {
10959                 if(p->camera_entity != rsurface.texture->camera_entity)
10960                         continue;
10961                 d = 0;
10962                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10963                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10964                 {
10965                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10966                         d += fabs(PlaneDiff(vert, &p->plane));
10967                 }
10968                 if (bestd > d || bestplaneindex < 0)
10969                 {
10970                         bestd = d;
10971                         bestplaneindex = planeindex;
10972                 }
10973         }
10974         return bestplaneindex;
10975 }
10976
10977 static void RSurf_BindReflectionForBatch(int planeindex)
10978 {
10979         // pick the closest matching water plane and bind textures
10980         r_waterstate_waterplane_t *bestp = planeindex >= 0 ? r_waterstate.waterplanes + planeindex : NULL;
10981         switch(vid.renderpath)
10982         {
10983         case RENDERPATH_CGGL:
10984 #ifdef SUPPORTCG
10985                 if (r_cg_permutation->fp_Texture_Refraction) {CG_BindTexture(r_cg_permutation->fp_Texture_Refraction, bestp ? bestp->texture_refraction : r_texture_black);CHECKCGERROR}
10986                 else if (r_cg_permutation->fp_Texture_First) {CG_BindTexture(r_cg_permutation->fp_Texture_First, bestp ? bestp->texture_camera : r_texture_black);CHECKCGERROR}
10987                 if (r_cg_permutation->fp_Texture_Reflection) {CG_BindTexture(r_cg_permutation->fp_Texture_Reflection, bestp ? bestp->texture_reflection : r_texture_black);CHECKCGERROR}
10988 #endif
10989                 break;
10990         case RENDERPATH_GL20:
10991                 if (r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION, bestp ? bestp->texture_refraction : r_texture_black);
10992                 else if (r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST, bestp ? bestp->texture_camera : r_texture_black);
10993                 if (r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION, bestp ? bestp->texture_reflection : r_texture_black);
10994                 break;
10995         case RENDERPATH_GL13:
10996         case RENDERPATH_GL11:
10997                 break;
10998         }
10999 }
11000
11001 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11002 {
11003         int i;
11004         for (i = 0;i < rsurface.batchnumvertices;i++)
11005                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11006         rsurface.passcolor4f = rsurface.array_passcolor4f;
11007         rsurface.passcolor4f_vertexbuffer = 0;
11008         rsurface.passcolor4f_bufferoffset = 0;
11009 }
11010
11011 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11012 {
11013         int i;
11014         float f;
11015         const float *v;
11016         const float *c;
11017         float *c2;
11018         if (rsurface.passcolor4f)
11019         {
11020                 // generate color arrays
11021                 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)
11022                 {
11023                         f = RSurf_FogVertex(v);
11024                         c2[0] = c[0] * f;
11025                         c2[1] = c[1] * f;
11026                         c2[2] = c[2] * f;
11027                         c2[3] = c[3];
11028                 }
11029         }
11030         else
11031         {
11032                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11033                 {
11034                         f = RSurf_FogVertex(v);
11035                         c2[0] = f;
11036                         c2[1] = f;
11037                         c2[2] = f;
11038                         c2[3] = 1;
11039                 }
11040         }
11041         rsurface.passcolor4f = rsurface.array_passcolor4f;
11042         rsurface.passcolor4f_vertexbuffer = 0;
11043         rsurface.passcolor4f_bufferoffset = 0;
11044 }
11045
11046 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11047 {
11048         int i;
11049         float f;
11050         const float *v;
11051         const float *c;
11052         float *c2;
11053         if (!rsurface.passcolor4f)
11054                 return;
11055         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)
11056         {
11057                 f = RSurf_FogVertex(v);
11058                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11059                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11060                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11061                 c2[3] = c[3];
11062         }
11063         rsurface.passcolor4f = rsurface.array_passcolor4f;
11064         rsurface.passcolor4f_vertexbuffer = 0;
11065         rsurface.passcolor4f_bufferoffset = 0;
11066 }
11067
11068 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11069 {
11070         int i;
11071         const float *c;
11072         float *c2;
11073         if (!rsurface.passcolor4f)
11074                 return;
11075         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11076         {
11077                 c2[0] = c[0] * r;
11078                 c2[1] = c[1] * g;
11079                 c2[2] = c[2] * b;
11080                 c2[3] = c[3] * a;
11081         }
11082         rsurface.passcolor4f = rsurface.array_passcolor4f;
11083         rsurface.passcolor4f_vertexbuffer = 0;
11084         rsurface.passcolor4f_bufferoffset = 0;
11085 }
11086
11087 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11088 {
11089         int i;
11090         const float *c;
11091         float *c2;
11092         if (!rsurface.passcolor4f)
11093                 return;
11094         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11095         {
11096                 c2[0] = c[0] + r_refdef.scene.ambient;
11097                 c2[1] = c[1] + r_refdef.scene.ambient;
11098                 c2[2] = c[2] + r_refdef.scene.ambient;
11099                 c2[3] = c[3];
11100         }
11101         rsurface.passcolor4f = rsurface.array_passcolor4f;
11102         rsurface.passcolor4f_vertexbuffer = 0;
11103         rsurface.passcolor4f_bufferoffset = 0;
11104 }
11105
11106 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11107 {
11108         // TODO: optimize
11109         rsurface.passcolor4f = NULL;
11110         rsurface.passcolor4f_vertexbuffer = 0;
11111         rsurface.passcolor4f_bufferoffset = 0;
11112         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11113         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11114         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11115         GL_Color(r, g, b, a);
11116         RSurf_BindLightmapForBatch();
11117         RSurf_DrawBatch();
11118 }
11119
11120 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11121 {
11122         // TODO: optimize applyfog && applycolor case
11123         // just apply fog if necessary, and tint the fog color array if necessary
11124         rsurface.passcolor4f = NULL;
11125         rsurface.passcolor4f_vertexbuffer = 0;
11126         rsurface.passcolor4f_bufferoffset = 0;
11127         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11128         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11129         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11130         GL_Color(r, g, b, a);
11131         RSurf_DrawBatch();
11132 }
11133
11134 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11135 {
11136         // TODO: optimize
11137         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11138         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11139         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11140         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11141         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11142         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11143         GL_Color(r, g, b, a);
11144         RSurf_DrawBatch();
11145 }
11146
11147 static void RSurf_DrawBatch_GL11_ClampColor(void)
11148 {
11149         int i;
11150         const float *c1;
11151         float *c2;
11152         if (!rsurface.passcolor4f)
11153                 return;
11154         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11155         {
11156                 c2[0] = bound(0.0f, c1[0], 1.0f);
11157                 c2[1] = bound(0.0f, c1[1], 1.0f);
11158                 c2[2] = bound(0.0f, c1[2], 1.0f);
11159                 c2[3] = bound(0.0f, c1[3], 1.0f);
11160         }
11161 }
11162
11163 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11164 {
11165         int i;
11166         float f;
11167         float alpha;
11168         const float *v;
11169         const float *n;
11170         float *c;
11171         vec3_t ambientcolor;
11172         vec3_t diffusecolor;
11173         vec3_t lightdir;
11174         // TODO: optimize
11175         // model lighting
11176         VectorCopy(rsurface.modellight_lightdir, lightdir);
11177         f = 0.5f * r_refdef.lightmapintensity;
11178         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11179         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11180         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11181         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11182         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11183         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11184         alpha = *a;
11185         if (VectorLength2(diffusecolor) > 0)
11186         {
11187                 // q3-style directional shading
11188                 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)
11189                 {
11190                         if ((f = DotProduct(n, lightdir)) > 0)
11191                                 VectorMA(ambientcolor, f, diffusecolor, c);
11192                         else
11193                                 VectorCopy(ambientcolor, c);
11194                         c[3] = alpha;
11195                 }
11196                 *r = 1;
11197                 *g = 1;
11198                 *b = 1;
11199                 *a = 1;
11200                 rsurface.passcolor4f = rsurface.array_passcolor4f;
11201                 rsurface.passcolor4f_vertexbuffer = 0;
11202                 rsurface.passcolor4f_bufferoffset = 0;
11203                 *applycolor = false;
11204         }
11205         else
11206         {
11207                 *r = ambientcolor[0];
11208                 *g = ambientcolor[1];
11209                 *b = ambientcolor[2];
11210                 rsurface.passcolor4f = NULL;
11211                 rsurface.passcolor4f_vertexbuffer = 0;
11212                 rsurface.passcolor4f_bufferoffset = 0;
11213         }
11214 }
11215
11216 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11217 {
11218         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11219         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11220         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11221         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11222         GL_Color(r, g, b, a);
11223         RSurf_DrawBatch();
11224 }
11225
11226 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11227 {
11228         int i;
11229         float f;
11230         const float *v;
11231         float *c;
11232         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11233         {
11234                 f = 1 - RSurf_FogVertex(v);
11235                 c[0] = r;
11236                 c[1] = g;
11237                 c[2] = b;
11238                 c[3] = f * a;
11239         }
11240 }
11241
11242 void RSurf_SetupDepthAndCulling(void)
11243 {
11244         // submodels are biased to avoid z-fighting with world surfaces that they
11245         // may be exactly overlapping (avoids z-fighting artifacts on certain
11246         // doors and things in Quake maps)
11247         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11248         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11249         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11250         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11251 }
11252
11253 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11254 {
11255         // transparent sky would be ridiculous
11256         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11257                 return;
11258         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11259         skyrenderlater = true;
11260         RSurf_SetupDepthAndCulling();
11261         GL_DepthMask(true);
11262         // LordHavoc: HalfLife maps have freaky skypolys so don't use
11263         // skymasking on them, and Quake3 never did sky masking (unlike
11264         // software Quake and software Quake2), so disable the sky masking
11265         // in Quake3 maps as it causes problems with q3map2 sky tricks,
11266         // and skymasking also looks very bad when noclipping outside the
11267         // level, so don't use it then either.
11268         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
11269         {
11270                 R_Mesh_ResetTextureState();
11271                 if (skyrendermasked)
11272                 {
11273                         R_SetupShader_DepthOrShadow();
11274                         // depth-only (masking)
11275                         GL_ColorMask(0,0,0,0);
11276                         // just to make sure that braindead drivers don't draw
11277                         // anything despite that colormask...
11278                         GL_BlendFunc(GL_ZERO, GL_ONE);
11279                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11280                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11281                 }
11282                 else
11283                 {
11284                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11285                         // fog sky
11286                         GL_BlendFunc(GL_ONE, GL_ZERO);
11287                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
11288                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
11289                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11290                 }
11291                 RSurf_DrawBatch();
11292                 if (skyrendermasked)
11293                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11294         }
11295         R_Mesh_ResetTextureState();
11296         GL_Color(1, 1, 1, 1);
11297 }
11298
11299 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
11300 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
11301 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11302 {
11303         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
11304                 return;
11305         if (prepass)
11306         {
11307                 // render screenspace normalmap to texture
11308                 GL_DepthMask(true);
11309                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist);
11310                 RSurf_DrawBatch();
11311                 return;
11312         }
11313
11314         // bind lightmap texture
11315
11316         // water/refraction/reflection/camera surfaces have to be handled specially
11317         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
11318         {
11319                 int start, end, startplaneindex;
11320                 for (start = 0;start < texturenumsurfaces;start = end)
11321                 {
11322                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
11323                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
11324                                 ;
11325                         // now that we have a batch using the same planeindex, render it
11326                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
11327                         {
11328                                 // render water or distortion background
11329                                 GL_DepthMask(true);
11330                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start);
11331                                 RSurf_BindReflectionForBatch(startplaneindex);
11332                                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11333                                         RSurf_BindLightmapForBatch();
11334                                 RSurf_DrawBatch();
11335                                 // blend surface on top
11336                                 GL_DepthMask(false);
11337                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start);
11338                                 RSurf_DrawBatch();
11339                         }
11340                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
11341                         {
11342                                 // render surface with reflection texture as input
11343                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11344                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start);
11345                                 RSurf_BindReflectionForBatch(startplaneindex);
11346                                 if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11347                                         RSurf_BindLightmapForBatch();
11348                                 RSurf_DrawBatch();
11349                         }
11350                 }
11351                 return;
11352         }
11353
11354         // render surface batch normally
11355         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11356         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist);
11357         if (rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
11358                 RSurf_BindLightmapForBatch();
11359         RSurf_DrawBatch();
11360 }
11361
11362 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11363 {
11364         // OpenGL 1.3 path - anything not completely ancient
11365         qboolean applycolor;
11366         qboolean applyfog;
11367         int layerindex;
11368         const texturelayer_t *layer;
11369         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);
11370         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11371
11372         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11373         {
11374                 vec4_t layercolor;
11375                 int layertexrgbscale;
11376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11377                 {
11378                         if (layerindex == 0)
11379                                 GL_AlphaTest(true);
11380                         else
11381                         {
11382                                 GL_AlphaTest(false);
11383                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11384                         }
11385                 }
11386                 GL_DepthMask(layer->depthmask && writedepth);
11387                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11388                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11389                 {
11390                         layertexrgbscale = 4;
11391                         VectorScale(layer->color, 0.25f, layercolor);
11392                 }
11393                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11394                 {
11395                         layertexrgbscale = 2;
11396                         VectorScale(layer->color, 0.5f, layercolor);
11397                 }
11398                 else
11399                 {
11400                         layertexrgbscale = 1;
11401                         VectorScale(layer->color, 1.0f, layercolor);
11402                 }
11403                 layercolor[3] = layer->color[3];
11404                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11405                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11406                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11407                 switch (layer->type)
11408                 {
11409                 case TEXTURELAYERTYPE_LITTEXTURE:
11410                         // single-pass lightmapped texture with 2x rgbscale
11411                         R_Mesh_TexBind(0, r_texture_white);
11412                         R_Mesh_TexMatrix(0, NULL);
11413                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11414                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11415                         R_Mesh_TexBind(1, layer->texture);
11416                         R_Mesh_TexMatrix(1, &layer->texmatrix);
11417                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11418                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11419                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11420                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11421                         else if (rsurface.uselightmaptexture)
11422                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11423                         else
11424                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11425                         break;
11426                 case TEXTURELAYERTYPE_TEXTURE:
11427                         // singletexture unlit texture with transparency support
11428                         R_Mesh_TexBind(0, layer->texture);
11429                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11430                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11431                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11432                         R_Mesh_TexBind(1, 0);
11433                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11434                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11435                         break;
11436                 case TEXTURELAYERTYPE_FOG:
11437                         // singletexture fogging
11438                         if (layer->texture)
11439                         {
11440                                 R_Mesh_TexBind(0, layer->texture);
11441                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11442                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11443                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11444                         }
11445                         else
11446                         {
11447                                 R_Mesh_TexBind(0, 0);
11448                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11449                         }
11450                         R_Mesh_TexBind(1, 0);
11451                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11452                         // generate a color array for the fog pass
11453                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11454                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11455                         RSurf_DrawBatch();
11456                         break;
11457                 default:
11458                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11459                 }
11460         }
11461         CHECKGLERROR
11462         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11463         {
11464                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11465                 GL_AlphaTest(false);
11466         }
11467 }
11468
11469 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11470 {
11471         // OpenGL 1.1 - crusty old voodoo path
11472         qboolean applyfog;
11473         int layerindex;
11474         const texturelayer_t *layer;
11475         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);
11476         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11477
11478         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11479         {
11480                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11481                 {
11482                         if (layerindex == 0)
11483                                 GL_AlphaTest(true);
11484                         else
11485                         {
11486                                 GL_AlphaTest(false);
11487                                 qglDepthFunc(GL_EQUAL);CHECKGLERROR
11488                         }
11489                 }
11490                 GL_DepthMask(layer->depthmask && writedepth);
11491                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11492                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11493                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11494                 switch (layer->type)
11495                 {
11496                 case TEXTURELAYERTYPE_LITTEXTURE:
11497                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
11498                         {
11499                                 // two-pass lit texture with 2x rgbscale
11500                                 // first the lightmap pass
11501                                 R_Mesh_TexBind(0, r_texture_white);
11502                                 R_Mesh_TexMatrix(0, NULL);
11503                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11504                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11505                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11506                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11507                                 else if (rsurface.uselightmaptexture)
11508                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11509                                 else
11510                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11511                                 // then apply the texture to it
11512                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11513                                 R_Mesh_TexBind(0, layer->texture);
11514                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11515                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11516                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11517                                 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);
11518                         }
11519                         else
11520                         {
11521                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11522                                 R_Mesh_TexBind(0, layer->texture);
11523                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11524                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11525                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11526                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11527                                         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);
11528                                 else
11529                                         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);
11530                         }
11531                         break;
11532                 case TEXTURELAYERTYPE_TEXTURE:
11533                         // singletexture unlit texture with transparency support
11534                         R_Mesh_TexBind(0, layer->texture);
11535                         R_Mesh_TexMatrix(0, &layer->texmatrix);
11536                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11537                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11538                         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);
11539                         break;
11540                 case TEXTURELAYERTYPE_FOG:
11541                         // singletexture fogging
11542                         if (layer->texture)
11543                         {
11544                                 R_Mesh_TexBind(0, layer->texture);
11545                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
11546                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11547                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11548                         }
11549                         else
11550                         {
11551                                 R_Mesh_TexBind(0, 0);
11552                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11553                         }
11554                         // generate a color array for the fog pass
11555                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
11556                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11557                         RSurf_DrawBatch();
11558                         break;
11559                 default:
11560                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11561                 }
11562         }
11563         CHECKGLERROR
11564         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11565         {
11566                 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
11567                 GL_AlphaTest(false);
11568         }
11569 }
11570
11571 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11572 {
11573         int vi;
11574         int j;
11575         r_vertexgeneric_t *batchvertex;
11576         float c[4];
11577
11578         GL_AlphaTest(false);
11579         R_Mesh_ResetTextureState();
11580         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11581
11582         if(rsurface.texture && rsurface.texture->currentskinframe)
11583         {
11584                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11585                 c[3] *= rsurface.texture->currentalpha;
11586         }
11587         else
11588         {
11589                 c[0] = 1;
11590                 c[1] = 0;
11591                 c[2] = 1;
11592                 c[3] = 1;
11593         }
11594
11595         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11596         {
11597                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11598                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11599                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11600         }
11601
11602         // brighten it up (as texture value 127 means "unlit")
11603         c[0] *= 2 * r_refdef.view.colorscale;
11604         c[1] *= 2 * r_refdef.view.colorscale;
11605         c[2] *= 2 * r_refdef.view.colorscale;
11606
11607         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11608                 c[3] *= r_wateralpha.value;
11609
11610         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11611         {
11612                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11613                 GL_DepthMask(false);
11614         }
11615         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11616         {
11617                 GL_BlendFunc(GL_ONE, GL_ONE);
11618                 GL_DepthMask(false);
11619         }
11620         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11621         {
11622                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11623                 GL_DepthMask(false);
11624         }
11625         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11626         {
11627                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11628                 GL_DepthMask(false);
11629         }
11630         else
11631         {
11632                 GL_BlendFunc(GL_ONE, GL_ZERO);
11633                 GL_DepthMask(writedepth);
11634         }
11635
11636         if (r_showsurfaces.integer == 3)
11637         {
11638                 rsurface.passcolor4f = NULL;
11639
11640                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11641                 {
11642                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11643
11644                         rsurface.passcolor4f = NULL;
11645                         rsurface.passcolor4f_vertexbuffer = 0;
11646                         rsurface.passcolor4f_bufferoffset = 0;
11647                 }
11648                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11649                 {
11650                         qboolean applycolor = true;
11651                         float one = 1.0;
11652
11653                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11654
11655                         r_refdef.lightmapintensity = 1;
11656                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11657                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11658                 }
11659                 else
11660                 {
11661                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11662
11663                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11664                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11665                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11666                 }
11667
11668                 if(!rsurface.passcolor4f)
11669                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11670
11671                 RSurf_DrawBatch_GL11_ApplyAmbient();
11672                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11673                 if(r_refdef.fogenabled)
11674                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11675                 RSurf_DrawBatch_GL11_ClampColor();
11676
11677                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11678                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11679                 RSurf_DrawBatch();
11680         }
11681         else if (!r_refdef.view.showdebug)
11682         {
11683                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11684                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11685                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11686                 {
11687                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11688                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
11689                 }
11690                 R_Mesh_PrepareVertices_Generic_Unlock();
11691                 RSurf_DrawBatch();
11692         }
11693         else if (r_showsurfaces.integer == 4)
11694         {
11695                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11696                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11697                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
11698                 {
11699                         unsigned char c = vi << 3;
11700                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11701                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
11702                 }
11703                 R_Mesh_PrepareVertices_Generic_Unlock();
11704                 RSurf_DrawBatch();
11705         }
11706         else if (r_showsurfaces.integer == 2)
11707         {
11708                 const int *e;
11709                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11710                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11711                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11712                 {
11713                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
11714                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11715                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11716                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11717                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
11718                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
11719                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
11720                 }
11721                 R_Mesh_PrepareVertices_Generic_Unlock();
11722                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11723         }
11724         else
11725         {
11726                 int texturesurfaceindex;
11727                 int k;
11728                 const msurface_t *surface;
11729                 unsigned char surfacecolor4ub[4];
11730                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11731                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11732                 vi = 0;
11733                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11734                 {
11735                         surface = texturesurfacelist[texturesurfaceindex];
11736                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11737                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
11738                         for (j = 0;j < surface->num_vertices;j++)
11739                         {
11740                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11741                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
11742                                 vi++;
11743                         }
11744                 }
11745                 R_Mesh_PrepareVertices_Generic_Unlock();
11746                 RSurf_DrawBatch();
11747         }
11748 }
11749
11750 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11751 {
11752         CHECKGLERROR
11753         RSurf_SetupDepthAndCulling();
11754         if (r_showsurfaces.integer)
11755         {
11756                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11757                 return;
11758         }
11759         switch (vid.renderpath)
11760         {
11761         case RENDERPATH_GL20:
11762         case RENDERPATH_CGGL:
11763                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11764                 break;
11765         case RENDERPATH_GL13:
11766                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11767                 break;
11768         case RENDERPATH_GL11:
11769                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11770                 break;
11771         }
11772         CHECKGLERROR
11773 }
11774
11775 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11776 {
11777         CHECKGLERROR
11778         RSurf_SetupDepthAndCulling();
11779         if (r_showsurfaces.integer)
11780         {
11781                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11782                 return;
11783         }
11784         switch (vid.renderpath)
11785         {
11786         case RENDERPATH_GL20:
11787         case RENDERPATH_CGGL:
11788                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11789                 break;
11790         case RENDERPATH_GL13:
11791                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11792                 break;
11793         case RENDERPATH_GL11:
11794                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11795                 break;
11796         }
11797         CHECKGLERROR
11798 }
11799
11800 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11801 {
11802         int i, j;
11803         int texturenumsurfaces, endsurface;
11804         texture_t *texture;
11805         const msurface_t *surface;
11806 #define MAXBATCH_TRANSPARENTSURFACES 256
11807         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
11808
11809         // if the model is static it doesn't matter what value we give for
11810         // wantnormals and wanttangents, so this logic uses only rules applicable
11811         // to a model, knowing that they are meaningless otherwise
11812         if (ent == r_refdef.scene.worldentity)
11813                 RSurf_ActiveWorldEntity();
11814         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11815                 RSurf_ActiveModelEntity(ent, false, false, false);
11816         else
11817         {
11818                 switch (vid.renderpath)
11819                 {
11820                 case RENDERPATH_GL20:
11821                 case RENDERPATH_CGGL:
11822                         RSurf_ActiveModelEntity(ent, true, true, false);
11823                         break;
11824                 case RENDERPATH_GL13:
11825                 case RENDERPATH_GL11:
11826                         RSurf_ActiveModelEntity(ent, true, false, false);
11827                         break;
11828                 }
11829         }
11830
11831         if (r_transparentdepthmasking.integer)
11832         {
11833                 qboolean setup = false;
11834                 for (i = 0;i < numsurfaces;i = j)
11835                 {
11836                         j = i + 1;
11837                         surface = rsurface.modelsurfaces + surfacelist[i];
11838                         texture = surface->texture;
11839                         rsurface.texture = R_GetCurrentTexture(texture);
11840                         rsurface.lightmaptexture = NULL;
11841                         rsurface.deluxemaptexture = NULL;
11842                         rsurface.uselightmaptexture = false;
11843                         // scan ahead until we find a different texture
11844                         endsurface = min(i + 1024, numsurfaces);
11845                         texturenumsurfaces = 0;
11846                         texturesurfacelist[texturenumsurfaces++] = surface;
11847                         for (;j < endsurface;j++)
11848                         {
11849                                 surface = rsurface.modelsurfaces + surfacelist[j];
11850                                 if (texture != surface->texture)
11851                                         break;
11852                                 texturesurfacelist[texturenumsurfaces++] = surface;
11853                         }
11854                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11855                                 continue;
11856                         // render the range of surfaces as depth
11857                         if (!setup)
11858                         {
11859                                 setup = true;
11860                                 GL_ColorMask(0,0,0,0);
11861                                 GL_Color(1,1,1,1);
11862                                 GL_DepthTest(true);
11863                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11864                                 GL_DepthMask(true);
11865                                 GL_AlphaTest(false);
11866                                 R_Mesh_ResetTextureState();
11867                                 R_SetupShader_DepthOrShadow();
11868                         }
11869                         RSurf_SetupDepthAndCulling();
11870                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11871                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11872                         RSurf_DrawBatch();
11873                 }
11874                 if (setup)
11875                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11876         }
11877
11878         for (i = 0;i < numsurfaces;i = j)
11879         {
11880                 j = i + 1;
11881                 surface = rsurface.modelsurfaces + surfacelist[i];
11882                 texture = surface->texture;
11883                 rsurface.texture = R_GetCurrentTexture(texture);
11884                 rsurface.lightmaptexture = surface->lightmaptexture;
11885                 rsurface.deluxemaptexture = surface->deluxemaptexture;
11886                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11887                 // scan ahead until we find a different texture
11888                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
11889                 texturenumsurfaces = 0;
11890                 texturesurfacelist[texturenumsurfaces++] = surface;
11891                 for (;j < endsurface;j++)
11892                 {
11893                         surface = rsurface.modelsurfaces + surfacelist[j];
11894                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11895                                 break;
11896                         texturesurfacelist[texturenumsurfaces++] = surface;
11897                 }
11898                 // render the range of surfaces
11899                 if (ent == r_refdef.scene.worldentity)
11900                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11901                 else
11902                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11903         }
11904         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11905         GL_AlphaTest(false);
11906 }
11907
11908 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
11909 {
11910         // transparent surfaces get pushed off into the transparent queue
11911         int surfacelistindex;
11912         const msurface_t *surface;
11913         vec3_t tempcenter, center;
11914         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11915         {
11916                 surface = texturesurfacelist[surfacelistindex];
11917                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11918                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11919                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11920                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11921                 if (queueentity->transparent_offset) // transparent offset
11922                 {
11923                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
11924                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
11925                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
11926                 }
11927                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
11928         }
11929 }
11930
11931 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11932 {
11933         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11934                 return;
11935         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11936                 return;
11937         RSurf_SetupDepthAndCulling();
11938         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
11939         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
11940         RSurf_DrawBatch();
11941 }
11942
11943 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11944 {
11945         const entity_render_t *queueentity = r_refdef.scene.worldentity;
11946         CHECKGLERROR
11947         if (depthonly)
11948                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11949         else if (prepass)
11950         {
11951                 if (!rsurface.texture->currentnumlayers)
11952                         return;
11953                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11954                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11955                 else
11956                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11957         }
11958         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
11959                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11960         else if (!rsurface.texture->currentnumlayers)
11961                 return;
11962         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
11963         {
11964                 // in the deferred case, transparent surfaces were queued during prepass
11965                 if (!r_shadow_usingdeferredprepass)
11966                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
11967         }
11968         else
11969         {
11970                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11971                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11972         }
11973         CHECKGLERROR
11974 }
11975
11976 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11977 {
11978         int i, j;
11979         texture_t *texture;
11980         // break the surface list down into batches by texture and use of lightmapping
11981         for (i = 0;i < numsurfaces;i = j)
11982         {
11983                 j = i + 1;
11984                 // texture is the base texture pointer, rsurface.texture is the
11985                 // current frame/skin the texture is directing us to use (for example
11986                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11987                 // use skin 1 instead)
11988                 texture = surfacelist[i]->texture;
11989                 rsurface.texture = R_GetCurrentTexture(texture);
11990                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11991                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11992                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
11993                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11994                 {
11995                         // if this texture is not the kind we want, skip ahead to the next one
11996                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11997                                 ;
11998                         continue;
11999                 }
12000                 // simply scan ahead until we find a different texture or lightmap state
12001                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12002                         ;
12003                 // render the range of surfaces
12004                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12005         }
12006 }
12007
12008 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12009 {
12010         CHECKGLERROR
12011         if (depthonly)
12012                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12013         else if (prepass)
12014         {
12015                 if (!rsurface.texture->currentnumlayers)
12016                         return;
12017                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12018                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12019                 else
12020                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12021         }
12022         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12023                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12024         else if (!rsurface.texture->currentnumlayers)
12025                 return;
12026         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12027         {
12028                 // in the deferred case, transparent surfaces were queued during prepass
12029                 if (!r_shadow_usingdeferredprepass)
12030                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12031         }
12032         else
12033         {
12034                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12035                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12036         }
12037         CHECKGLERROR
12038 }
12039
12040 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12041 {
12042         int i, j;
12043         texture_t *texture;
12044         // break the surface list down into batches by texture and use of lightmapping
12045         for (i = 0;i < numsurfaces;i = j)
12046         {
12047                 j = i + 1;
12048                 // texture is the base texture pointer, rsurface.texture is the
12049                 // current frame/skin the texture is directing us to use (for example
12050                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12051                 // use skin 1 instead)
12052                 texture = surfacelist[i]->texture;
12053                 rsurface.texture = R_GetCurrentTexture(texture);
12054                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12055                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12056                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12057                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12058                 {
12059                         // if this texture is not the kind we want, skip ahead to the next one
12060                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12061                                 ;
12062                         continue;
12063                 }
12064                 // simply scan ahead until we find a different texture or lightmap state
12065                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12066                         ;
12067                 // render the range of surfaces
12068                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12069         }
12070 }
12071
12072 float locboxvertex3f[6*4*3] =
12073 {
12074         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12075         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12076         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12077         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12078         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12079         1,0,0, 0,0,0, 0,1,0, 1,1,0
12080 };
12081
12082 unsigned short locboxelements[6*2*3] =
12083 {
12084          0, 1, 2, 0, 2, 3,
12085          4, 5, 6, 4, 6, 7,
12086          8, 9,10, 8,10,11,
12087         12,13,14, 12,14,15,
12088         16,17,18, 16,18,19,
12089         20,21,22, 20,22,23
12090 };
12091
12092 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12093 {
12094         int i, j;
12095         cl_locnode_t *loc = (cl_locnode_t *)ent;
12096         vec3_t mins, size;
12097         float vertex3f[6*4*3];
12098         CHECKGLERROR
12099         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12100         GL_DepthMask(false);
12101         GL_DepthRange(0, 1);
12102         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12103         GL_DepthTest(true);
12104         GL_CullFace(GL_NONE);
12105         R_EntityMatrix(&identitymatrix);
12106
12107         R_Mesh_ResetTextureState();
12108
12109         i = surfacelist[0];
12110         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12111                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12112                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12113                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12114
12115         if (VectorCompare(loc->mins, loc->maxs))
12116         {
12117                 VectorSet(size, 2, 2, 2);
12118                 VectorMA(loc->mins, -0.5f, size, mins);
12119         }
12120         else
12121         {
12122                 VectorCopy(loc->mins, mins);
12123                 VectorSubtract(loc->maxs, loc->mins, size);
12124         }
12125
12126         for (i = 0;i < 6*4*3;)
12127                 for (j = 0;j < 3;j++, i++)
12128                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12129
12130         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12131         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12132         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12133 }
12134
12135 void R_DrawLocs(void)
12136 {
12137         int index;
12138         cl_locnode_t *loc, *nearestloc;
12139         vec3_t center;
12140         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12141         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12142         {
12143                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12144                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12145         }
12146 }
12147
12148 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12149 {
12150         if (decalsystem->decals)
12151                 Mem_Free(decalsystem->decals);
12152         memset(decalsystem, 0, sizeof(*decalsystem));
12153 }
12154
12155 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)
12156 {
12157         tridecal_t *decal;
12158         tridecal_t *decals;
12159         int i;
12160
12161         // expand or initialize the system
12162         if (decalsystem->maxdecals <= decalsystem->numdecals)
12163         {
12164                 decalsystem_t old = *decalsystem;
12165                 qboolean useshortelements;
12166                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12167                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12168                 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)));
12169                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12170                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12171                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12172                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12173                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12174                 if (decalsystem->numdecals)
12175                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12176                 if (old.decals)
12177                         Mem_Free(old.decals);
12178                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12179                         decalsystem->element3i[i] = i;
12180                 if (useshortelements)
12181                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12182                                 decalsystem->element3s[i] = i;
12183         }
12184
12185         // grab a decal and search for another free slot for the next one
12186         decals = decalsystem->decals;
12187         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12188         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12189                 ;
12190         decalsystem->freedecal = i;
12191         if (decalsystem->numdecals <= i)
12192                 decalsystem->numdecals = i + 1;
12193
12194         // initialize the decal
12195         decal->lived = 0;
12196         decal->triangleindex = triangleindex;
12197         decal->surfaceindex = surfaceindex;
12198         decal->decalsequence = decalsequence;
12199         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
12200         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
12201         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
12202         decal->color4ub[0][3] = 255;
12203         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
12204         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
12205         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
12206         decal->color4ub[1][3] = 255;
12207         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
12208         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
12209         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
12210         decal->color4ub[2][3] = 255;
12211         decal->vertex3f[0][0] = v0[0];
12212         decal->vertex3f[0][1] = v0[1];
12213         decal->vertex3f[0][2] = v0[2];
12214         decal->vertex3f[1][0] = v1[0];
12215         decal->vertex3f[1][1] = v1[1];
12216         decal->vertex3f[1][2] = v1[2];
12217         decal->vertex3f[2][0] = v2[0];
12218         decal->vertex3f[2][1] = v2[1];
12219         decal->vertex3f[2][2] = v2[2];
12220         decal->texcoord2f[0][0] = t0[0];
12221         decal->texcoord2f[0][1] = t0[1];
12222         decal->texcoord2f[1][0] = t1[0];
12223         decal->texcoord2f[1][1] = t1[1];
12224         decal->texcoord2f[2][0] = t2[0];
12225         decal->texcoord2f[2][1] = t2[1];
12226 }
12227
12228 extern cvar_t cl_decals_bias;
12229 extern cvar_t cl_decals_models;
12230 extern cvar_t cl_decals_newsystem_intensitymultiplier;
12231 // baseparms, parms, temps
12232 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
12233 {
12234         int cornerindex;
12235         int index;
12236         float v[9][3];
12237         const float *vertex3f;
12238         int numpoints;
12239         float points[2][9][3];
12240         float temp[3];
12241         float tc[9][2];
12242         float f;
12243         float c[9][4];
12244         const int *e;
12245
12246         e = rsurface.modelelement3i + 3*triangleindex;
12247
12248         vertex3f = rsurface.modelvertex3f;
12249
12250         for (cornerindex = 0;cornerindex < 3;cornerindex++)
12251         {
12252                 index = 3*e[cornerindex];
12253                 VectorCopy(vertex3f + index, v[cornerindex]);
12254         }
12255         // cull backfaces
12256         //TriangleNormal(v[0], v[1], v[2], normal);
12257         //if (DotProduct(normal, localnormal) < 0.0f)
12258         //      continue;
12259         // clip by each of the box planes formed from the projection matrix
12260         // if anything survives, we emit the decal
12261         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]);
12262         if (numpoints < 3)
12263                 return;
12264         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]);
12265         if (numpoints < 3)
12266                 return;
12267         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]);
12268         if (numpoints < 3)
12269                 return;
12270         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]);
12271         if (numpoints < 3)
12272                 return;
12273         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]);
12274         if (numpoints < 3)
12275                 return;
12276         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]);
12277         if (numpoints < 3)
12278                 return;
12279         // some part of the triangle survived, so we have to accept it...
12280         if (dynamic)
12281         {
12282                 // dynamic always uses the original triangle
12283                 numpoints = 3;
12284                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12285                 {
12286                         index = 3*e[cornerindex];
12287                         VectorCopy(vertex3f + index, v[cornerindex]);
12288                 }
12289         }
12290         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12291         {
12292                 // convert vertex positions to texcoords
12293                 Matrix4x4_Transform(projection, v[cornerindex], temp);
12294                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12295                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12296                 // calculate distance fade from the projection origin
12297                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12298                 f = bound(0.0f, f, 1.0f);
12299                 c[cornerindex][0] = r * f;
12300                 c[cornerindex][1] = g * f;
12301                 c[cornerindex][2] = b * f;
12302                 c[cornerindex][3] = 1.0f;
12303                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12304         }
12305         if (dynamic)
12306                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
12307         else
12308                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12309                         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);
12310 }
12311 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)
12312 {
12313         matrix4x4_t projection;
12314         decalsystem_t *decalsystem;
12315         qboolean dynamic;
12316         dp_model_t *model;
12317         const msurface_t *surface;
12318         const msurface_t *surfaces;
12319         const int *surfacelist;
12320         const texture_t *texture;
12321         int numtriangles;
12322         int numsurfacelist;
12323         int surfacelistindex;
12324         int surfaceindex;
12325         int triangleindex;
12326         float localorigin[3];
12327         float localnormal[3];
12328         float localmins[3];
12329         float localmaxs[3];
12330         float localsize;
12331         //float normal[3];
12332         float planes[6][4];
12333         float angles[3];
12334         bih_t *bih;
12335         int bih_triangles_count;
12336         int bih_triangles[256];
12337         int bih_surfaces[256];
12338
12339         decalsystem = &ent->decalsystem;
12340         model = ent->model;
12341         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12342         {
12343                 R_DecalSystem_Reset(&ent->decalsystem);
12344                 return;
12345         }
12346
12347         if (!model->brush.data_nodes && !cl_decals_models.integer)
12348         {
12349                 if (decalsystem->model)
12350                         R_DecalSystem_Reset(decalsystem);
12351                 return;
12352         }
12353
12354         if (decalsystem->model != model)
12355                 R_DecalSystem_Reset(decalsystem);
12356         decalsystem->model = model;
12357
12358         RSurf_ActiveModelEntity(ent, false, false, false);
12359
12360         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12361         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12362         VectorNormalize(localnormal);
12363         localsize = worldsize*rsurface.inversematrixscale;
12364         localmins[0] = localorigin[0] - localsize;
12365         localmins[1] = localorigin[1] - localsize;
12366         localmins[2] = localorigin[2] - localsize;
12367         localmaxs[0] = localorigin[0] + localsize;
12368         localmaxs[1] = localorigin[1] + localsize;
12369         localmaxs[2] = localorigin[2] + localsize;
12370
12371         //VectorCopy(localnormal, planes[4]);
12372         //VectorVectors(planes[4], planes[2], planes[0]);
12373         AnglesFromVectors(angles, localnormal, NULL, false);
12374         AngleVectors(angles, planes[0], planes[2], planes[4]);
12375         VectorNegate(planes[0], planes[1]);
12376         VectorNegate(planes[2], planes[3]);
12377         VectorNegate(planes[4], planes[5]);
12378         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12379         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12380         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12381         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12382         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12383         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12384
12385 #if 1
12386 // works
12387 {
12388         matrix4x4_t forwardprojection;
12389         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12390         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12391 }
12392 #else
12393 // broken
12394 {
12395         float projectionvector[4][3];
12396         VectorScale(planes[0], ilocalsize, projectionvector[0]);
12397         VectorScale(planes[2], ilocalsize, projectionvector[1]);
12398         VectorScale(planes[4], ilocalsize, projectionvector[2]);
12399         projectionvector[0][0] = planes[0][0] * ilocalsize;
12400         projectionvector[0][1] = planes[1][0] * ilocalsize;
12401         projectionvector[0][2] = planes[2][0] * ilocalsize;
12402         projectionvector[1][0] = planes[0][1] * ilocalsize;
12403         projectionvector[1][1] = planes[1][1] * ilocalsize;
12404         projectionvector[1][2] = planes[2][1] * ilocalsize;
12405         projectionvector[2][0] = planes[0][2] * ilocalsize;
12406         projectionvector[2][1] = planes[1][2] * ilocalsize;
12407         projectionvector[2][2] = planes[2][2] * ilocalsize;
12408         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12409         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12410         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12411         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12412 }
12413 #endif
12414
12415         dynamic = model->surfmesh.isanimated;
12416         numsurfacelist = model->nummodelsurfaces;
12417         surfacelist = model->sortedmodelsurfaces;
12418         surfaces = model->data_surfaces;
12419
12420         bih = NULL;
12421         bih_triangles_count = -1;
12422         if(!dynamic)
12423         {
12424                 if(model->render_bih.numleafs)
12425                         bih = &model->render_bih;
12426                 else if(model->collision_bih.numleafs)
12427                         bih = &model->collision_bih;
12428         }
12429         if(bih)
12430                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12431         if(bih_triangles_count == 0)
12432                 return;
12433         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12434                 return;
12435         if(bih_triangles_count > 0)
12436         {
12437                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12438                 {
12439                         surfaceindex = bih_surfaces[triangleindex];
12440                         surface = surfaces + surfaceindex;
12441                         texture = surface->texture;
12442                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12443                                 continue;
12444                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12445                                 continue;
12446                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12447                 }
12448         }
12449         else
12450         {
12451                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12452                 {
12453                         surfaceindex = surfacelist[surfacelistindex];
12454                         surface = surfaces + surfaceindex;
12455                         // check cull box first because it rejects more than any other check
12456                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12457                                 continue;
12458                         // skip transparent surfaces
12459                         texture = surface->texture;
12460                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12461                                 continue;
12462                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12463                                 continue;
12464                         numtriangles = surface->num_triangles;
12465                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12466                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12467                 }
12468         }
12469 }
12470
12471 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12472 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)
12473 {
12474         int renderentityindex;
12475         float worldmins[3];
12476         float worldmaxs[3];
12477         entity_render_t *ent;
12478
12479         if (!cl_decals_newsystem.integer)
12480                 return;
12481
12482         worldmins[0] = worldorigin[0] - worldsize;
12483         worldmins[1] = worldorigin[1] - worldsize;
12484         worldmins[2] = worldorigin[2] - worldsize;
12485         worldmaxs[0] = worldorigin[0] + worldsize;
12486         worldmaxs[1] = worldorigin[1] + worldsize;
12487         worldmaxs[2] = worldorigin[2] + worldsize;
12488
12489         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12490
12491         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12492         {
12493                 ent = r_refdef.scene.entities[renderentityindex];
12494                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12495                         continue;
12496
12497                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12498         }
12499 }
12500
12501 typedef struct r_decalsystem_splatqueue_s
12502 {
12503         vec3_t worldorigin;
12504         vec3_t worldnormal;
12505         float color[4];
12506         float tcrange[4];
12507         float worldsize;
12508         int decalsequence;
12509 }
12510 r_decalsystem_splatqueue_t;
12511
12512 int r_decalsystem_numqueued = 0;
12513 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12514
12515 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)
12516 {
12517         r_decalsystem_splatqueue_t *queue;
12518
12519         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12520                 return;
12521
12522         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12523         VectorCopy(worldorigin, queue->worldorigin);
12524         VectorCopy(worldnormal, queue->worldnormal);
12525         Vector4Set(queue->color, r, g, b, a);
12526         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12527         queue->worldsize = worldsize;
12528         queue->decalsequence = cl.decalsequence++;
12529 }
12530
12531 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12532 {
12533         int i;
12534         r_decalsystem_splatqueue_t *queue;
12535
12536         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12537                 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);
12538         r_decalsystem_numqueued = 0;
12539 }
12540
12541 extern cvar_t cl_decals_max;
12542 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12543 {
12544         int i;
12545         decalsystem_t *decalsystem = &ent->decalsystem;
12546         int numdecals;
12547         int killsequence;
12548         tridecal_t *decal;
12549         float frametime;
12550         float lifetime;
12551
12552         if (!decalsystem->numdecals)
12553                 return;
12554
12555         if (r_showsurfaces.integer)
12556                 return;
12557
12558         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12559         {
12560                 R_DecalSystem_Reset(decalsystem);
12561                 return;
12562         }
12563
12564         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
12565         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12566
12567         if (decalsystem->lastupdatetime)
12568                 frametime = (cl.time - decalsystem->lastupdatetime);
12569         else
12570                 frametime = 0;
12571         decalsystem->lastupdatetime = cl.time;
12572         decal = decalsystem->decals;
12573         numdecals = decalsystem->numdecals;
12574
12575         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12576         {
12577                 if (decal->color4ub[0][3])
12578                 {
12579                         decal->lived += frametime;
12580                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
12581                         {
12582                                 memset(decal, 0, sizeof(*decal));
12583                                 if (decalsystem->freedecal > i)
12584                                         decalsystem->freedecal = i;
12585                         }
12586                 }
12587         }
12588         decal = decalsystem->decals;
12589         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
12590                 numdecals--;
12591
12592         // collapse the array by shuffling the tail decals into the gaps
12593         for (;;)
12594         {
12595                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
12596                         decalsystem->freedecal++;
12597                 if (decalsystem->freedecal == numdecals)
12598                         break;
12599                 decal[decalsystem->freedecal] = decal[--numdecals];
12600         }
12601
12602         decalsystem->numdecals = numdecals;
12603
12604         if (numdecals <= 0)
12605         {
12606                 // if there are no decals left, reset decalsystem
12607                 R_DecalSystem_Reset(decalsystem);
12608         }
12609 }
12610
12611 extern skinframe_t *decalskinframe;
12612 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12613 {
12614         int i;
12615         decalsystem_t *decalsystem = &ent->decalsystem;
12616         int numdecals;
12617         tridecal_t *decal;
12618         float faderate;
12619         float alpha;
12620         float *v3f;
12621         float *c4f;
12622         float *t2f;
12623         const int *e;
12624         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12625         int numtris = 0;
12626
12627         numdecals = decalsystem->numdecals;
12628         if (!numdecals)
12629                 return;
12630
12631         if (r_showsurfaces.integer)
12632                 return;
12633
12634         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12635         {
12636                 R_DecalSystem_Reset(decalsystem);
12637                 return;
12638         }
12639
12640         // if the model is static it doesn't matter what value we give for
12641         // wantnormals and wanttangents, so this logic uses only rules applicable
12642         // to a model, knowing that they are meaningless otherwise
12643         if (ent == r_refdef.scene.worldentity)
12644                 RSurf_ActiveWorldEntity();
12645         else
12646                 RSurf_ActiveModelEntity(ent, false, false, false);
12647
12648         decalsystem->lastupdatetime = cl.time;
12649         decal = decalsystem->decals;
12650
12651         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12652
12653         // update vertex positions for animated models
12654         v3f = decalsystem->vertex3f;
12655         c4f = decalsystem->color4f;
12656         t2f = decalsystem->texcoord2f;
12657         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12658         {
12659                 if (!decal->color4ub[0][3])
12660                         continue;
12661
12662                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12663                         continue;
12664
12665                 // update color values for fading decals
12666                 if (decal->lived >= cl_decals_time.value)
12667                 {
12668                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12669                         alpha *= (1.0f/255.0f);
12670                 }
12671                 else
12672                         alpha = 1.0f/255.0f;
12673
12674                 c4f[ 0] = decal->color4ub[0][0] * alpha;
12675                 c4f[ 1] = decal->color4ub[0][1] * alpha;
12676                 c4f[ 2] = decal->color4ub[0][2] * alpha;
12677                 c4f[ 3] = 1;
12678                 c4f[ 4] = decal->color4ub[1][0] * alpha;
12679                 c4f[ 5] = decal->color4ub[1][1] * alpha;
12680                 c4f[ 6] = decal->color4ub[1][2] * alpha;
12681                 c4f[ 7] = 1;
12682                 c4f[ 8] = decal->color4ub[2][0] * alpha;
12683                 c4f[ 9] = decal->color4ub[2][1] * alpha;
12684                 c4f[10] = decal->color4ub[2][2] * alpha;
12685                 c4f[11] = 1;
12686
12687                 t2f[0] = decal->texcoord2f[0][0];
12688                 t2f[1] = decal->texcoord2f[0][1];
12689                 t2f[2] = decal->texcoord2f[1][0];
12690                 t2f[3] = decal->texcoord2f[1][1];
12691                 t2f[4] = decal->texcoord2f[2][0];
12692                 t2f[5] = decal->texcoord2f[2][1];
12693
12694                 // update vertex positions for animated models
12695                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12696                 {
12697                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12698                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
12699                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
12700                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
12701                 }
12702                 else
12703                 {
12704                         VectorCopy(decal->vertex3f[0], v3f);
12705                         VectorCopy(decal->vertex3f[1], v3f + 3);
12706                         VectorCopy(decal->vertex3f[2], v3f + 6);
12707                 }
12708
12709                 if (r_refdef.fogenabled)
12710                 {
12711                         alpha = RSurf_FogVertex(v3f);
12712                         VectorScale(c4f, alpha, c4f);
12713                         alpha = RSurf_FogVertex(v3f + 3);
12714                         VectorScale(c4f + 4, alpha, c4f + 4);
12715                         alpha = RSurf_FogVertex(v3f + 6);
12716                         VectorScale(c4f + 8, alpha, c4f + 8);
12717                 }
12718
12719                 v3f += 9;
12720                 c4f += 12;
12721                 t2f += 6;
12722                 numtris++;
12723         }
12724
12725         if (numtris > 0)
12726         {
12727                 r_refdef.stats.drawndecals += numtris;
12728
12729                 // now render the decals all at once
12730                 // (this assumes they all use one particle font texture!)
12731                 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);
12732                 R_Mesh_ResetTextureState();
12733                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12734                 GL_DepthMask(false);
12735                 GL_DepthRange(0, 1);
12736                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12737                 GL_DepthTest(true);
12738                 GL_CullFace(GL_NONE);
12739                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12740                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
12741                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12742         }
12743 }
12744
12745 static void R_DrawModelDecals(void)
12746 {
12747         int i, numdecals;
12748
12749         // fade faster when there are too many decals
12750         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12751         for (i = 0;i < r_refdef.scene.numentities;i++)
12752                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12753
12754         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12755         for (i = 0;i < r_refdef.scene.numentities;i++)
12756                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12757                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12758
12759         R_DecalSystem_ApplySplatEntitiesQueue();
12760
12761         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12762         for (i = 0;i < r_refdef.scene.numentities;i++)
12763                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12764
12765         r_refdef.stats.totaldecals += numdecals;
12766
12767         if (r_showsurfaces.integer)
12768                 return;
12769
12770         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12771
12772         for (i = 0;i < r_refdef.scene.numentities;i++)
12773         {
12774                 if (!r_refdef.viewcache.entityvisible[i])
12775                         continue;
12776                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12777                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12778         }
12779 }
12780
12781 extern cvar_t mod_collision_bih;
12782 void R_DrawDebugModel(void)
12783 {
12784         entity_render_t *ent = rsurface.entity;
12785         int i, j, k, l, flagsmask;
12786         const msurface_t *surface;
12787         dp_model_t *model = ent->model;
12788         vec3_t v;
12789
12790         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12791
12792         R_Mesh_ResetTextureState();
12793         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12794         GL_DepthRange(0, 1);
12795         GL_DepthTest(!r_showdisabledepthtest.integer);
12796         GL_DepthMask(false);
12797         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12798
12799         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12800         {
12801                 int triangleindex;
12802                 int bihleafindex;
12803                 qboolean cullbox = ent == r_refdef.scene.worldentity;
12804                 const q3mbrush_t *brush;
12805                 const bih_t *bih = &model->collision_bih;
12806                 const bih_leaf_t *bihleaf;
12807                 float vertex3f[3][3];
12808                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12809                 cullbox = false;
12810                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12811                 {
12812                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12813                                 continue;
12814                         switch (bihleaf->type)
12815                         {
12816                         case BIH_BRUSH:
12817                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12818                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12819                                 {
12820                                         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);
12821                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12822                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12823                                 }
12824                                 break;
12825                         case BIH_COLLISIONTRIANGLE:
12826                                 triangleindex = bihleaf->itemindex;
12827                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12828                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12829                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12830                                 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);
12831                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12832                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12833                                 break;
12834                         case BIH_RENDERTRIANGLE:
12835                                 triangleindex = bihleaf->itemindex;
12836                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12837                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12838                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12839                                 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);
12840                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12841                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12842                                 break;
12843                         }
12844                 }
12845         }
12846
12847         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12848
12849         if (r_showtris.integer || r_shownormals.integer)
12850         {
12851                 if (r_showdisabledepthtest.integer)
12852                 {
12853                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12854                         GL_DepthMask(false);
12855                 }
12856                 else
12857                 {
12858                         GL_BlendFunc(GL_ONE, GL_ZERO);
12859                         GL_DepthMask(true);
12860                 }
12861                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12862                 {
12863                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12864                                 continue;
12865                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12866                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12867                         {
12868                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12869                                 if (r_showtris.value > 0)
12870                                 {
12871                                         if (!rsurface.texture->currentlayers->depthmask)
12872                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12873                                         else if (ent == r_refdef.scene.worldentity)
12874                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12875                                         else
12876                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12877                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12878                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
12879                                         RSurf_DrawBatch();
12880                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
12881                                         CHECKGLERROR
12882                                 }
12883                                 if (r_shownormals.value < 0)
12884                                 {
12885                                         qglBegin(GL_LINES);
12886                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12887                                         {
12888                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12889                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12890                                                 qglVertex3f(v[0], v[1], v[2]);
12891                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12892                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12893                                                 qglVertex3f(v[0], v[1], v[2]);
12894                                         }
12895                                         qglEnd();
12896                                         CHECKGLERROR
12897                                 }
12898                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12899                                 {
12900                                         qglBegin(GL_LINES);
12901                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12902                                         {
12903                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12904                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12905                                                 qglVertex3f(v[0], v[1], v[2]);
12906                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12907                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12908                                                 qglVertex3f(v[0], v[1], v[2]);
12909                                         }
12910                                         qglEnd();
12911                                         CHECKGLERROR
12912                                         qglBegin(GL_LINES);
12913                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12914                                         {
12915                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12916                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12917                                                 qglVertex3f(v[0], v[1], v[2]);
12918                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12919                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12920                                                 qglVertex3f(v[0], v[1], v[2]);
12921                                         }
12922                                         qglEnd();
12923                                         CHECKGLERROR
12924                                         qglBegin(GL_LINES);
12925                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
12926                                         {
12927                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12928                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12929                                                 qglVertex3f(v[0], v[1], v[2]);
12930                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12931                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
12932                                                 qglVertex3f(v[0], v[1], v[2]);
12933                                         }
12934                                         qglEnd();
12935                                         CHECKGLERROR
12936                                 }
12937                         }
12938                 }
12939                 rsurface.texture = NULL;
12940         }
12941 }
12942
12943 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
12944 int r_maxsurfacelist = 0;
12945 const msurface_t **r_surfacelist = NULL;
12946 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12947 {
12948         int i, j, endj, flagsmask;
12949         dp_model_t *model = r_refdef.scene.worldmodel;
12950         msurface_t *surfaces;
12951         unsigned char *update;
12952         int numsurfacelist = 0;
12953         if (model == NULL)
12954                 return;
12955
12956         if (r_maxsurfacelist < model->num_surfaces)
12957         {
12958                 r_maxsurfacelist = model->num_surfaces;
12959                 if (r_surfacelist)
12960                         Mem_Free((msurface_t**)r_surfacelist);
12961                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12962         }
12963
12964         RSurf_ActiveWorldEntity();
12965
12966         surfaces = model->data_surfaces;
12967         update = model->brushq1.lightmapupdateflags;
12968
12969         // update light styles on this submodel
12970         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12971         {
12972                 model_brush_lightstyleinfo_t *style;
12973                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12974                 {
12975                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12976                         {
12977                                 int *list = style->surfacelist;
12978                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12979                                 for (j = 0;j < style->numsurfaces;j++)
12980                                         update[list[j]] = true;
12981                         }
12982                 }
12983         }
12984
12985         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12986
12987         if (debug)
12988         {
12989                 R_DrawDebugModel();
12990                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12991                 return;
12992         }
12993
12994         rsurface.lightmaptexture = NULL;
12995         rsurface.deluxemaptexture = NULL;
12996         rsurface.uselightmaptexture = false;
12997         rsurface.texture = NULL;
12998         rsurface.rtlight = NULL;
12999         numsurfacelist = 0;
13000         // add visible surfaces to draw list
13001         for (i = 0;i < model->nummodelsurfaces;i++)
13002         {
13003                 j = model->sortedmodelsurfaces[i];
13004                 if (r_refdef.viewcache.world_surfacevisible[j])
13005                         r_surfacelist[numsurfacelist++] = surfaces + j;
13006         }
13007         // update lightmaps if needed
13008         if (model->brushq1.firstrender)
13009         {
13010                 model->brushq1.firstrender = false;
13011                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13012                         if (update[j])
13013                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13014         }
13015         else if (update)
13016         {
13017                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13018                         if (r_refdef.viewcache.world_surfacevisible[j])
13019                                 if (update[j])
13020                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13021         }
13022         // don't do anything if there were no surfaces
13023         if (!numsurfacelist)
13024         {
13025                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13026                 return;
13027         }
13028         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13029         GL_AlphaTest(false);
13030
13031         // add to stats if desired
13032         if (r_speeds.integer && !skysurfaces && !depthonly)
13033         {
13034                 r_refdef.stats.world_surfaces += numsurfacelist;
13035                 for (j = 0;j < numsurfacelist;j++)
13036                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13037         }
13038
13039         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13040 }
13041
13042 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13043 {
13044         int i, j, endj, flagsmask;
13045         dp_model_t *model = ent->model;
13046         msurface_t *surfaces;
13047         unsigned char *update;
13048         int numsurfacelist = 0;
13049         if (model == NULL)
13050                 return;
13051
13052         if (r_maxsurfacelist < model->num_surfaces)
13053         {
13054                 r_maxsurfacelist = model->num_surfaces;
13055                 if (r_surfacelist)
13056                         Mem_Free((msurface_t **)r_surfacelist);
13057                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13058         }
13059
13060         // if the model is static it doesn't matter what value we give for
13061         // wantnormals and wanttangents, so this logic uses only rules applicable
13062         // to a model, knowing that they are meaningless otherwise
13063         if (ent == r_refdef.scene.worldentity)
13064                 RSurf_ActiveWorldEntity();
13065         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13066                 RSurf_ActiveModelEntity(ent, false, false, false);
13067         else if (prepass)
13068                 RSurf_ActiveModelEntity(ent, true, true, true);
13069         else if (depthonly)
13070         {
13071                 switch (vid.renderpath)
13072                 {
13073                 case RENDERPATH_GL20:
13074                 case RENDERPATH_CGGL:
13075                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13076                         break;
13077                 case RENDERPATH_GL13:
13078                 case RENDERPATH_GL11:
13079                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13080                         break;
13081                 }
13082         }
13083         else
13084         {
13085                 switch (vid.renderpath)
13086                 {
13087                 case RENDERPATH_GL20:
13088                 case RENDERPATH_CGGL:
13089                         RSurf_ActiveModelEntity(ent, true, true, false);
13090                         break;
13091                 case RENDERPATH_GL13:
13092                 case RENDERPATH_GL11:
13093                         RSurf_ActiveModelEntity(ent, true, false, false);
13094                         break;
13095                 }
13096         }
13097
13098         surfaces = model->data_surfaces;
13099         update = model->brushq1.lightmapupdateflags;
13100
13101         // update light styles
13102         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13103         {
13104                 model_brush_lightstyleinfo_t *style;
13105                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13106                 {
13107                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13108                         {
13109                                 int *list = style->surfacelist;
13110                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13111                                 for (j = 0;j < style->numsurfaces;j++)
13112                                         update[list[j]] = true;
13113                         }
13114                 }
13115         }
13116
13117         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13118
13119         if (debug)
13120         {
13121                 R_DrawDebugModel();
13122                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13123                 return;
13124         }
13125
13126         rsurface.lightmaptexture = NULL;
13127         rsurface.deluxemaptexture = NULL;
13128         rsurface.uselightmaptexture = false;
13129         rsurface.texture = NULL;
13130         rsurface.rtlight = NULL;
13131         numsurfacelist = 0;
13132         // add visible surfaces to draw list
13133         for (i = 0;i < model->nummodelsurfaces;i++)
13134                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13135         // don't do anything if there were no surfaces
13136         if (!numsurfacelist)
13137         {
13138                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13139                 return;
13140         }
13141         // update lightmaps if needed
13142         if (update)
13143         {
13144                 int updated = 0;
13145                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13146                 {
13147                         if (update[j])
13148                         {
13149                                 updated++;
13150                                 R_BuildLightMap(ent, surfaces + j);
13151                         }
13152                 }
13153         }
13154         if (update)
13155                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13156                         if (update[j])
13157                                 R_BuildLightMap(ent, surfaces + j);
13158         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13159         GL_AlphaTest(false);
13160
13161         // add to stats if desired
13162         if (r_speeds.integer && !skysurfaces && !depthonly)
13163         {
13164                 r_refdef.stats.entities_surfaces += numsurfacelist;
13165                 for (j = 0;j < numsurfacelist;j++)
13166                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
13167         }
13168
13169         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13170 }
13171
13172 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
13173 {
13174         static texture_t texture;
13175         static msurface_t surface;
13176         const msurface_t *surfacelist = &surface;
13177
13178         // fake enough texture and surface state to render this geometry
13179
13180         texture.update_lastrenderframe = -1; // regenerate this texture
13181         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13182         texture.currentskinframe = skinframe;
13183         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13184         texture.offsetmapping = OFFSETMAPPING_OFF;
13185         texture.offsetscale = 1;
13186         texture.specularscalemod = 1;
13187         texture.specularpowermod = 1;
13188
13189         surface.texture = &texture;
13190         surface.num_triangles = numtriangles;
13191         surface.num_firsttriangle = firsttriangle;
13192         surface.num_vertices = numvertices;
13193         surface.num_firstvertex = firstvertex;
13194
13195         // now render it
13196         rsurface.texture = R_GetCurrentTexture(surface.texture);
13197         rsurface.lightmaptexture = NULL;
13198         rsurface.deluxemaptexture = NULL;
13199         rsurface.uselightmaptexture = false;
13200         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13201 }
13202
13203 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)
13204 {
13205         static msurface_t surface;
13206         const msurface_t *surfacelist = &surface;
13207
13208         // fake enough texture and surface state to render this geometry
13209
13210         surface.texture = texture;
13211         surface.num_triangles = numtriangles;
13212         surface.num_firsttriangle = firsttriangle;
13213         surface.num_vertices = numvertices;
13214         surface.num_firstvertex = firstvertex;
13215
13216         // now render it
13217         rsurface.texture = R_GetCurrentTexture(surface.texture);
13218         rsurface.lightmaptexture = NULL;
13219         rsurface.deluxemaptexture = NULL;
13220         rsurface.uselightmaptexture = false;
13221         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13222 }