]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added debug shaderflags used by the shader compiler which is needed to debug the...
[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 #ifdef SUPPORTD3D
32 #include <d3d9.h>
33 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
34 #endif
35
36 mempool_t *r_main_mempool;
37 rtexturepool_t *r_main_texturepool;
38
39 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
40
41 static qboolean r_loadnormalmap;
42 static qboolean r_loadgloss;
43 qboolean r_loadfog;
44 static qboolean r_loaddds;
45 static qboolean r_savedds;
46
47 //
48 // screen size info
49 //
50 r_refdef_t r_refdef;
51
52 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
53 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
54 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
55 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
56 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)"};
57 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
59 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
60
61 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
62 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"};
63 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
64 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)"};
65 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
66
67 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"};
68 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
69 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
70 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
71 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
72 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
73 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)"};
74 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
75 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
76 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"};
77 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"};
78 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
83 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
84 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
85 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
86 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
87 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
88 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
89 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)"};
90 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)"};
91 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
92 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
93 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
94 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
95 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
96 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
97 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
98 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."};
99 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
100 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
101 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
102 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."};
103 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
104 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
105 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
106 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
107 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"};
108 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"};
109 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
110 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
111 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
112 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
113 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"};
114
115 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
116 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
117 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
118 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
119 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
120 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
121 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
122 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
123
124 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)"};
125 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"};
126
127 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
128 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
129 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
130 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
131 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
132
133 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
134 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
135 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
136
137 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)"};
138 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
139 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
140 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
141 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
142 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)"};
143 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)"};
144 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)"};
145 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)"};
146
147 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)"};
148 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
149 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"};
150 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
151 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
152
153 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
154 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
155 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
156 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
157
158 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
159 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
160 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
161 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
162 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
163 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exagerated the glow is"};
164 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
165
166 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
167 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
168 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
169 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)"};
170
171 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"};
172
173 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"};
174
175 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
176
177 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
178 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"};
179 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accodringly, 2: Make it a continuous rotation"};
180 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
181 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
182 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "0.15", "fake perspective effect for SPR_OVERHEAD sprites"};
183 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)"};
184
185 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
186
187 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)"};
188
189 extern cvar_t v_glslgamma;
190
191 extern qboolean v_flipped_state;
192
193 static struct r_bloomstate_s
194 {
195         qboolean enabled;
196         qboolean hdr;
197
198         int bloomwidth, bloomheight;
199
200         int screentexturewidth, screentextureheight;
201         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
202
203         int bloomtexturewidth, bloomtextureheight;
204         rtexture_t *texture_bloom;
205
206         // arrays for rendering the screen passes
207         float screentexcoord2f[8];
208         float bloomtexcoord2f[8];
209         float offsettexcoord2f[8];
210
211         r_viewport_t viewport;
212 }
213 r_bloomstate;
214
215 r_waterstate_t r_waterstate;
216
217 /// shadow volume bsp struct with automatically growing nodes buffer
218 svbsp_t r_svbsp;
219
220 rtexture_t *r_texture_blanknormalmap;
221 rtexture_t *r_texture_white;
222 rtexture_t *r_texture_grey128;
223 rtexture_t *r_texture_black;
224 rtexture_t *r_texture_notexture;
225 rtexture_t *r_texture_whitecube;
226 rtexture_t *r_texture_normalizationcube;
227 rtexture_t *r_texture_fogattenuation;
228 rtexture_t *r_texture_fogheighttexture;
229 rtexture_t *r_texture_gammaramps;
230 unsigned int r_texture_gammaramps_serial;
231 //rtexture_t *r_texture_fogintensity;
232 rtexture_t *r_texture_reflectcube;
233
234 // TODO: hash lookups?
235 typedef struct cubemapinfo_s
236 {
237         char basename[64];
238         rtexture_t *texture;
239 }
240 cubemapinfo_t;
241
242 int r_texture_numcubemaps;
243 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
244
245 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
246 unsigned int r_numqueries;
247 unsigned int r_maxqueries;
248
249 typedef struct r_qwskincache_s
250 {
251         char name[MAX_QPATH];
252         skinframe_t *skinframe;
253 }
254 r_qwskincache_t;
255
256 static r_qwskincache_t *r_qwskincache;
257 static int r_qwskincache_size;
258
259 /// vertex coordinates for a quad that covers the screen exactly
260 extern const float r_screenvertex3f[12];
261 extern const float r_d3dscreenvertex3f[12];
262 const float r_screenvertex3f[12] =
263 {
264         0, 0, 0,
265         1, 0, 0,
266         1, 1, 0,
267         0, 1, 0
268 };
269 const float r_d3dscreenvertex3f[12] =
270 {
271         0, 1, 0,
272         1, 1, 0,
273         1, 0, 0,
274         0, 0, 0
275 };
276
277 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
278 {
279         int i;
280         for (i = 0;i < verts;i++)
281         {
282                 out[0] = in[0] * r;
283                 out[1] = in[1] * g;
284                 out[2] = in[2] * b;
285                 out[3] = in[3];
286                 in += 4;
287                 out += 4;
288         }
289 }
290
291 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = r;
297                 out[1] = g;
298                 out[2] = b;
299                 out[3] = a;
300                 out += 4;
301         }
302 }
303
304 // FIXME: move this to client?
305 void FOG_clear(void)
306 {
307         if (gamemode == GAME_NEHAHRA)
308         {
309                 Cvar_Set("gl_fogenable", "0");
310                 Cvar_Set("gl_fogdensity", "0.2");
311                 Cvar_Set("gl_fogred", "0.3");
312                 Cvar_Set("gl_foggreen", "0.3");
313                 Cvar_Set("gl_fogblue", "0.3");
314         }
315         r_refdef.fog_density = 0;
316         r_refdef.fog_red = 0;
317         r_refdef.fog_green = 0;
318         r_refdef.fog_blue = 0;
319         r_refdef.fog_alpha = 1;
320         r_refdef.fog_start = 0;
321         r_refdef.fog_end = 16384;
322         r_refdef.fog_height = 1<<30;
323         r_refdef.fog_fadedepth = 128;
324         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
325 }
326
327 static void R_BuildBlankTextures(void)
328 {
329         unsigned char data[4];
330         data[2] = 128; // normal X
331         data[1] = 128; // normal Y
332         data[0] = 255; // normal Z
333         data[3] = 128; // height
334         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
335         data[0] = 255;
336         data[1] = 255;
337         data[2] = 255;
338         data[3] = 255;
339         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
340         data[0] = 128;
341         data[1] = 128;
342         data[2] = 128;
343         data[3] = 255;
344         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
345         data[0] = 0;
346         data[1] = 0;
347         data[2] = 0;
348         data[3] = 255;
349         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
350 }
351
352 static void R_BuildNoTexture(void)
353 {
354         int x, y;
355         unsigned char pix[16][16][4];
356         // this makes a light grey/dark grey checkerboard texture
357         for (y = 0;y < 16;y++)
358         {
359                 for (x = 0;x < 16;x++)
360                 {
361                         if ((y < 8) ^ (x < 8))
362                         {
363                                 pix[y][x][0] = 128;
364                                 pix[y][x][1] = 128;
365                                 pix[y][x][2] = 128;
366                                 pix[y][x][3] = 255;
367                         }
368                         else
369                         {
370                                 pix[y][x][0] = 64;
371                                 pix[y][x][1] = 64;
372                                 pix[y][x][2] = 64;
373                                 pix[y][x][3] = 255;
374                         }
375                 }
376         }
377         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
378 }
379
380 static void R_BuildWhiteCube(void)
381 {
382         unsigned char data[6*1*1*4];
383         memset(data, 255, sizeof(data));
384         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNormalizationCube(void)
388 {
389         int x, y, side;
390         vec3_t v;
391         vec_t s, t, intensity;
392 #define NORMSIZE 64
393         unsigned char *data;
394         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
395         for (side = 0;side < 6;side++)
396         {
397                 for (y = 0;y < NORMSIZE;y++)
398                 {
399                         for (x = 0;x < NORMSIZE;x++)
400                         {
401                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
402                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
403                                 switch(side)
404                                 {
405                                 default:
406                                 case 0:
407                                         v[0] = 1;
408                                         v[1] = -t;
409                                         v[2] = -s;
410                                         break;
411                                 case 1:
412                                         v[0] = -1;
413                                         v[1] = -t;
414                                         v[2] = s;
415                                         break;
416                                 case 2:
417                                         v[0] = s;
418                                         v[1] = 1;
419                                         v[2] = t;
420                                         break;
421                                 case 3:
422                                         v[0] = s;
423                                         v[1] = -1;
424                                         v[2] = -t;
425                                         break;
426                                 case 4:
427                                         v[0] = s;
428                                         v[1] = -t;
429                                         v[2] = 1;
430                                         break;
431                                 case 5:
432                                         v[0] = -s;
433                                         v[1] = -t;
434                                         v[2] = -1;
435                                         break;
436                                 }
437                                 intensity = 127.0f / sqrt(DotProduct(v, v));
438                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
439                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
440                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
441                                 data[((side*64+y)*64+x)*4+3] = 255;
442                         }
443                 }
444         }
445         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
446         Mem_Free(data);
447 }
448
449 static void R_BuildFogTexture(void)
450 {
451         int x, b;
452 #define FOGWIDTH 256
453         unsigned char data1[FOGWIDTH][4];
454         //unsigned char data2[FOGWIDTH][4];
455         double d, r, alpha;
456
457         r_refdef.fogmasktable_start = r_refdef.fog_start;
458         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
459         r_refdef.fogmasktable_range = r_refdef.fogrange;
460         r_refdef.fogmasktable_density = r_refdef.fog_density;
461
462         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
463         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
464         {
465                 d = (x * r - r_refdef.fogmasktable_start);
466                 if(developer_extra.integer)
467                         Con_DPrintf("%f ", d);
468                 d = max(0, d);
469                 if (r_fog_exp2.integer)
470                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
471                 else
472                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
473                 if(developer_extra.integer)
474                         Con_DPrintf(" : %f ", alpha);
475                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
476                 if(developer_extra.integer)
477                         Con_DPrintf(" = %f\n", alpha);
478                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
479         }
480
481         for (x = 0;x < FOGWIDTH;x++)
482         {
483                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
484                 data1[x][0] = b;
485                 data1[x][1] = b;
486                 data1[x][2] = b;
487                 data1[x][3] = 255;
488                 //data2[x][0] = 255 - b;
489                 //data2[x][1] = 255 - b;
490                 //data2[x][2] = 255 - b;
491                 //data2[x][3] = 255;
492         }
493         if (r_texture_fogattenuation)
494         {
495                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
496                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
497         }
498         else
499         {
500                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
501                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
502         }
503 }
504
505 static void R_BuildFogHeightTexture(void)
506 {
507         unsigned char *inpixels;
508         int size;
509         int x;
510         int y;
511         int j;
512         float c[4];
513         float f;
514         inpixels = NULL;
515         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
516         if (r_refdef.fogheighttexturename[0])
517                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
518         if (!inpixels)
519         {
520                 r_refdef.fog_height_tablesize = 0;
521                 if (r_texture_fogheighttexture)
522                         R_FreeTexture(r_texture_fogheighttexture);
523                 r_texture_fogheighttexture = NULL;
524                 if (r_refdef.fog_height_table2d)
525                         Mem_Free(r_refdef.fog_height_table2d);
526                 r_refdef.fog_height_table2d = NULL;
527                 if (r_refdef.fog_height_table1d)
528                         Mem_Free(r_refdef.fog_height_table1d);
529                 r_refdef.fog_height_table1d = NULL;
530                 return;
531         }
532         size = image_width;
533         r_refdef.fog_height_tablesize = size;
534         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
535         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
536         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
537         Mem_Free(inpixels);
538         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
539         // average fog color table accounting for every fog layer between a point
540         // and the camera.  (Note: attenuation is handled separately!)
541         for (y = 0;y < size;y++)
542         {
543                 for (x = 0;x < size;x++)
544                 {
545                         Vector4Clear(c);
546                         f = 0;
547                         if (x < y)
548                         {
549                                 for (j = x;j <= y;j++)
550                                 {
551                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
552                                         f++;
553                                 }
554                         }
555                         else
556                         {
557                                 for (j = x;j >= y;j--)
558                                 {
559                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
560                                         f++;
561                                 }
562                         }
563                         f = 1.0f / f;
564                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
565                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
566                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
567                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
568                 }
569         }
570         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
571 }
572
573 //=======================================================================================================================================================
574
575 static const char *builtinshaderstring =
576 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
577 "// written by Forest 'LordHavoc' Hale\n"
578 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
579 "\n"
580 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
581 "# define USEFOG\n"
582 "#endif\n"
583 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
584 "#define USELIGHTMAP\n"
585 "#endif\n"
586 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
587 "#define USEEYEVECTOR\n"
588 "#endif\n"
589 "\n"
590 "#if defined(USESHADOWMAPRECT) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USEDEFERREDLIGHTMAP)\n"
591 "# extension GL_ARB_texture_rectangle : enable\n"
592 "#endif\n"
593 "\n"
594 "#ifdef USESHADOWMAP2D\n"
595 "# ifdef GL_EXT_gpu_shader4\n"
596 "#   extension GL_EXT_gpu_shader4 : enable\n"
597 "# endif\n"
598 "# ifdef GL_ARB_texture_gather\n"
599 "#   extension GL_ARB_texture_gather : enable\n"
600 "# else\n"
601 "#   ifdef GL_AMD_texture_texture4\n"
602 "#     extension GL_AMD_texture_texture4 : enable\n"
603 "#   endif\n"
604 "# endif\n"
605 "#endif\n"
606 "\n"
607 "#ifdef USESHADOWMAPCUBE\n"
608 "# extension GL_EXT_gpu_shader4 : enable\n"
609 "#endif\n"
610 "\n"
611 "//#ifdef USESHADOWSAMPLER\n"
612 "//# extension GL_ARB_shadow : enable\n"
613 "//#endif\n"
614 "\n"
615 "//#ifdef __GLSL_CG_DATA_TYPES\n"
616 "//# define myhalf half\n"
617 "//# define myhalf2 half2\n"
618 "//# define myhalf3 half3\n"
619 "//# define myhalf4 half4\n"
620 "//#else\n"
621 "# define myhalf float\n"
622 "# define myhalf2 vec2\n"
623 "# define myhalf3 vec3\n"
624 "# define myhalf4 vec4\n"
625 "//#endif\n"
626 "\n"
627 "#ifdef VERTEX_SHADER\n"
628 "uniform mat4 ModelViewProjectionMatrix;\n"
629 "#endif\n"
630 "\n"
631 "#ifdef MODE_DEPTH_OR_SHADOW\n"
632 "#ifdef VERTEX_SHADER\n"
633 "void main(void)\n"
634 "{\n"
635 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
636 "}\n"
637 "#endif\n"
638 "#else // !MODE_DEPTH_ORSHADOW\n"
639 "\n"
640 "\n"
641 "\n"
642 "\n"
643 "#ifdef MODE_SHOWDEPTH\n"
644 "#ifdef VERTEX_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
648 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
649 "}\n"
650 "#endif\n"
651 "\n"
652 "#ifdef FRAGMENT_SHADER\n"
653 "void main(void)\n"
654 "{\n"
655 "       gl_FragColor = gl_Color;\n"
656 "}\n"
657 "#endif\n"
658 "#else // !MODE_SHOWDEPTH\n"
659 "\n"
660 "\n"
661 "\n"
662 "\n"
663 "#ifdef MODE_POSTPROCESS\n"
664 "varying vec2 TexCoord1;\n"
665 "varying vec2 TexCoord2;\n"
666 "\n"
667 "#ifdef VERTEX_SHADER\n"
668 "void main(void)\n"
669 "{\n"
670 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
671 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
672 "#ifdef USEBLOOM\n"
673 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
674 "#endif\n"
675 "}\n"
676 "#endif\n"
677 "\n"
678 "#ifdef FRAGMENT_SHADER\n"
679 "uniform sampler2D Texture_First;\n"
680 "#ifdef USEBLOOM\n"
681 "uniform sampler2D Texture_Second;\n"
682 "uniform vec4 BloomColorSubtract;\n"
683 "#endif\n"
684 "#ifdef USEGAMMARAMPS\n"
685 "uniform sampler2D Texture_GammaRamps;\n"
686 "#endif\n"
687 "#ifdef USESATURATION\n"
688 "uniform float Saturation;\n"
689 "#endif\n"
690 "#ifdef USEVIEWTINT\n"
691 "uniform vec4 ViewTintColor;\n"
692 "#endif\n"
693 "//uncomment these if you want to use them:\n"
694 "uniform vec4 UserVec1;\n"
695 "uniform vec4 UserVec2;\n"
696 "// uniform vec4 UserVec3;\n"
697 "// uniform vec4 UserVec4;\n"
698 "// uniform float ClientTime;\n"
699 "uniform vec2 PixelSize;\n"
700 "void main(void)\n"
701 "{\n"
702 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
703 "#ifdef USEBLOOM\n"
704 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
705 "#endif\n"
706 "#ifdef USEVIEWTINT\n"
707 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
708 "#endif\n"
709 "\n"
710 "#ifdef USEPOSTPROCESSING\n"
711 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
712 "// 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"
713 "       float sobel = 1.0;\n"
714 "       // vec2 ts = textureSize(Texture_First, 0);\n"
715 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
716 "       vec2 px = PixelSize;\n"
717 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
718 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
719 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
720 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
721 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
722 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
723 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
724 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
725 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
728 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
729 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
730 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
731 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
732 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
733 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
734 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
735 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
736 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
737 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
738 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
739 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
740 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
741 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
742 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
743 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
744 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
745 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
746 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
747 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
748 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
749 "#endif\n"
750 "\n"
751 "#ifdef USESATURATION\n"
752 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
753 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
754 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
755 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
756 "#endif\n"
757 "\n"
758 "#ifdef USEGAMMARAMPS\n"
759 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
760 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
761 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
762 "#endif\n"
763 "}\n"
764 "#endif\n"
765 "#else // !MODE_POSTPROCESS\n"
766 "\n"
767 "\n"
768 "\n"
769 "\n"
770 "#ifdef MODE_GENERIC\n"
771 "#ifdef USEDIFFUSE\n"
772 "varying vec2 TexCoord1;\n"
773 "#endif\n"
774 "#ifdef USESPECULAR\n"
775 "varying vec2 TexCoord2;\n"
776 "#endif\n"
777 "#ifdef VERTEX_SHADER\n"
778 "void main(void)\n"
779 "{\n"
780 "       gl_FrontColor = gl_Color;\n"
781 "#ifdef USEDIFFUSE\n"
782 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
783 "#endif\n"
784 "#ifdef USESPECULAR\n"
785 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
786 "#endif\n"
787 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
788 "}\n"
789 "#endif\n"
790 "\n"
791 "#ifdef FRAGMENT_SHADER\n"
792 "#ifdef USEDIFFUSE\n"
793 "uniform sampler2D Texture_First;\n"
794 "#endif\n"
795 "#ifdef USESPECULAR\n"
796 "uniform sampler2D Texture_Second;\n"
797 "#endif\n"
798 "\n"
799 "void main(void)\n"
800 "{\n"
801 "       gl_FragColor = gl_Color;\n"
802 "#ifdef USEDIFFUSE\n"
803 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
804 "#endif\n"
805 "\n"
806 "#ifdef USESPECULAR\n"
807 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
808 "# ifdef USECOLORMAPPING\n"
809 "       gl_FragColor *= tex2;\n"
810 "# endif\n"
811 "# ifdef USEGLOW\n"
812 "       gl_FragColor += tex2;\n"
813 "# endif\n"
814 "# ifdef USEVERTEXTEXTUREBLEND\n"
815 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
816 "# endif\n"
817 "#endif\n"
818 "}\n"
819 "#endif\n"
820 "#else // !MODE_GENERIC\n"
821 "\n"
822 "\n"
823 "\n"
824 "\n"
825 "#ifdef MODE_BLOOMBLUR\n"
826 "varying TexCoord;\n"
827 "#ifdef VERTEX_SHADER\n"
828 "void main(void)\n"
829 "{\n"
830 "       gl_FrontColor = gl_Color;\n"
831 "       TexCoord = gl_MultiTexCoord0.xy;\n"
832 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
833 "}\n"
834 "#endif\n"
835 "\n"
836 "#ifdef FRAGMENT_SHADER\n"
837 "uniform sampler2D Texture_First;\n"
838 "uniform vec4 BloomBlur_Parameters;\n"
839 "\n"
840 "void main(void)\n"
841 "{\n"
842 "       int i;\n"
843 "       vec2 tc = TexCoord;\n"
844 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
845 "       tc += BloomBlur_Parameters.xy;\n"
846 "       for (i = 1;i < SAMPLES;i++)\n"
847 "       {\n"
848 "               color += texture2D(Texture_First, tc).rgb;\n"
849 "               tc += BloomBlur_Parameters.xy;\n"
850 "       }\n"
851 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
852 "}\n"
853 "#endif\n"
854 "#else // !MODE_BLOOMBLUR\n"
855 "#ifdef MODE_REFRACTION\n"
856 "varying vec2 TexCoord;\n"
857 "varying vec4 ModelViewProjectionPosition;\n"
858 "uniform mat4 TexMatrix;\n"
859 "#ifdef VERTEX_SHADER\n"
860 "\n"
861 "void main(void)\n"
862 "{\n"
863 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
864 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
865 "       ModelViewProjectionPosition = gl_Position;\n"
866 "}\n"
867 "#endif\n"
868 "\n"
869 "#ifdef FRAGMENT_SHADER\n"
870 "uniform sampler2D Texture_Normal;\n"
871 "uniform sampler2D Texture_Refraction;\n"
872 "uniform sampler2D Texture_Reflection;\n"
873 "\n"
874 "uniform vec4 DistortScaleRefractReflect;\n"
875 "uniform vec4 ScreenScaleRefractReflect;\n"
876 "uniform vec4 ScreenCenterRefractReflect;\n"
877 "uniform vec4 RefractColor;\n"
878 "uniform vec4 ReflectColor;\n"
879 "uniform float ReflectFactor;\n"
880 "uniform float ReflectOffset;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
885 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
886 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
887 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
888 "       // FIXME temporary hack to detect the case that the reflection\n"
889 "       // gets blackened at edges due to leaving the area that contains actual\n"
890 "       // content.\n"
891 "       // Remove this 'ack once we have a better way to stop this thing from\n"
892 "       // 'appening.\n"
893 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
894 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
895 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
896 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
897 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
898 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
899 "}\n"
900 "#endif\n"
901 "#else // !MODE_REFRACTION\n"
902 "\n"
903 "\n"
904 "\n"
905 "\n"
906 "#ifdef MODE_WATER\n"
907 "varying vec2 TexCoord;\n"
908 "varying vec3 EyeVector;\n"
909 "varying vec4 ModelViewProjectionPosition;\n"
910 "#ifdef VERTEX_SHADER\n"
911 "uniform vec3 EyePosition;\n"
912 "uniform mat4 TexMatrix;\n"
913 "\n"
914 "void main(void)\n"
915 "{\n"
916 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
917 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
918 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
919 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
920 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
921 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
922 "       ModelViewProjectionPosition = gl_Position;\n"
923 "}\n"
924 "#endif\n"
925 "\n"
926 "#ifdef FRAGMENT_SHADER\n"
927 "uniform sampler2D Texture_Normal;\n"
928 "uniform sampler2D Texture_Refraction;\n"
929 "uniform sampler2D Texture_Reflection;\n"
930 "\n"
931 "uniform vec4 DistortScaleRefractReflect;\n"
932 "uniform vec4 ScreenScaleRefractReflect;\n"
933 "uniform vec4 ScreenCenterRefractReflect;\n"
934 "uniform vec4 RefractColor;\n"
935 "uniform vec4 ReflectColor;\n"
936 "uniform float ReflectFactor;\n"
937 "uniform float ReflectOffset;\n"
938 "\n"
939 "void main(void)\n"
940 "{\n"
941 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
942 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
943 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
944 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
945 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
946 "       // FIXME temporary hack to detect the case that the reflection\n"
947 "       // gets blackened at edges due to leaving the area that contains actual\n"
948 "       // content.\n"
949 "       // Remove this 'ack once we have a better way to stop this thing from\n"
950 "       // 'appening.\n"
951 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
952 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
953 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
954 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
955 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
956 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
957 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
958 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
959 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
960 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
961 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
962 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
963 "}\n"
964 "#endif\n"
965 "#else // !MODE_WATER\n"
966 "\n"
967 "\n"
968 "\n"
969 "\n"
970 "// common definitions between vertex shader and fragment shader:\n"
971 "\n"
972 "varying vec2 TexCoord;\n"
973 "#ifdef USEVERTEXTEXTUREBLEND\n"
974 "varying vec2 TexCoord2;\n"
975 "#endif\n"
976 "#ifdef USELIGHTMAP\n"
977 "varying vec2 TexCoordLightmap;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef MODE_LIGHTSOURCE\n"
981 "varying vec3 CubeVector;\n"
982 "#endif\n"
983 "\n"
984 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
985 "varying vec3 LightVector;\n"
986 "#endif\n"
987 "\n"
988 "#ifdef USEEYEVECTOR\n"
989 "varying vec3 EyeVector;\n"
990 "#endif\n"
991 "#ifdef USEFOG\n"
992 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
993 "#endif\n"
994 "\n"
995 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
996 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
997 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
998 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef USEREFLECTION\n"
1002 "varying vec4 ModelViewProjectionPosition;\n"
1003 "#endif\n"
1004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1005 "uniform vec3 LightPosition;\n"
1006 "varying vec4 ModelViewPosition;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "uniform vec3 LightPosition;\n"
1011 "#endif\n"
1012 "uniform vec3 EyePosition;\n"
1013 "#ifdef MODE_LIGHTDIRECTION\n"
1014 "uniform vec3 LightDir;\n"
1015 "#endif\n"
1016 "uniform vec4 FogPlane;\n"
1017 "\n"
1018 "#ifdef USESHADOWMAPORTHO\n"
1019 "varying vec3 ShadowMapTC;\n"
1020 "#endif\n"
1021 "\n"
1022 "\n"
1023 "\n"
1024 "\n"
1025 "\n"
1026 "// 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"
1027 "\n"
1028 "// fragment shader specific:\n"
1029 "#ifdef FRAGMENT_SHADER\n"
1030 "\n"
1031 "uniform sampler2D Texture_Normal;\n"
1032 "uniform sampler2D Texture_Color;\n"
1033 "uniform sampler2D Texture_Gloss;\n"
1034 "#ifdef USEGLOW\n"
1035 "uniform sampler2D Texture_Glow;\n"
1036 "#endif\n"
1037 "#ifdef USEVERTEXTEXTUREBLEND\n"
1038 "uniform sampler2D Texture_SecondaryNormal;\n"
1039 "uniform sampler2D Texture_SecondaryColor;\n"
1040 "uniform sampler2D Texture_SecondaryGloss;\n"
1041 "#ifdef USEGLOW\n"
1042 "uniform sampler2D Texture_SecondaryGlow;\n"
1043 "#endif\n"
1044 "#endif\n"
1045 "#ifdef USECOLORMAPPING\n"
1046 "uniform sampler2D Texture_Pants;\n"
1047 "uniform sampler2D Texture_Shirt;\n"
1048 "#endif\n"
1049 "#ifdef USEFOG\n"
1050 "#ifdef USEFOGHEIGHTTEXTURE\n"
1051 "uniform sampler2D Texture_FogHeightTexture;\n"
1052 "#endif\n"
1053 "uniform sampler2D Texture_FogMask;\n"
1054 "#endif\n"
1055 "#ifdef USELIGHTMAP\n"
1056 "uniform sampler2D Texture_Lightmap;\n"
1057 "#endif\n"
1058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1059 "uniform sampler2D Texture_Deluxemap;\n"
1060 "#endif\n"
1061 "#ifdef USEREFLECTION\n"
1062 "uniform sampler2D Texture_Reflection;\n"
1063 "#endif\n"
1064 "\n"
1065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1066 "uniform sampler2D Texture_ScreenDepth;\n"
1067 "uniform sampler2D Texture_ScreenNormalMap;\n"
1068 "#endif\n"
1069 "#ifdef USEDEFERREDLIGHTMAP\n"
1070 "uniform sampler2D Texture_ScreenDiffuse;\n"
1071 "uniform sampler2D Texture_ScreenSpecular;\n"
1072 "#endif\n"
1073 "\n"
1074 "uniform myhalf3 Color_Pants;\n"
1075 "uniform myhalf3 Color_Shirt;\n"
1076 "uniform myhalf3 FogColor;\n"
1077 "\n"
1078 "#ifdef USEFOG\n"
1079 "uniform float FogRangeRecip;\n"
1080 "uniform float FogPlaneViewDist;\n"
1081 "uniform float FogHeightFade;\n"
1082 "vec3 FogVertex(vec3 surfacecolor)\n"
1083 "{\n"
1084 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1085 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1086 "       float fogfrac;\n"
1087 "#ifdef USEFOGHEIGHTTEXTURE\n"
1088 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1089 "       fogfrac = fogheightpixel.a;\n"
1090 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1091 "#else\n"
1092 "# ifdef USEFOGOUTSIDE\n"
1093 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1094 "# else\n"
1095 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1096 "# endif\n"
1097 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1098 "#endif\n"
1099 "}\n"
1100 "#endif\n"
1101 "\n"
1102 "#ifdef USEOFFSETMAPPING\n"
1103 "uniform float OffsetMapping_Scale;\n"
1104 "vec2 OffsetMapping(vec2 TexCoord)\n"
1105 "{\n"
1106 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1107 "       // 14 sample relief mapping: linear search and then binary search\n"
1108 "       // this basically steps forward a small amount repeatedly until it finds\n"
1109 "       // itself inside solid, then jitters forward and back using decreasing\n"
1110 "       // amounts to find the impact\n"
1111 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1112 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1113 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1114 "       vec3 RT = vec3(TexCoord, 1);\n"
1115 "       OffsetVector *= 0.1;\n"
1116 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1117 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1118 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1119 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1120 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1121 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1122 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1123 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1124 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1125 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1126 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1127 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1128 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1129 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1130 "       return RT.xy;\n"
1131 "#else\n"
1132 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1133 "       // this basically moves forward the full distance, and then backs up based\n"
1134 "       // on height of samples\n"
1135 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1136 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1137 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1138 "       TexCoord += OffsetVector;\n"
1139 "       OffsetVector *= 0.333;\n"
1140 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1141 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1142 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1143 "       return TexCoord;\n"
1144 "#endif\n"
1145 "}\n"
1146 "#endif // USEOFFSETMAPPING\n"
1147 "\n"
1148 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1149 "uniform sampler2D Texture_Attenuation;\n"
1150 "uniform samplerCube Texture_Cube;\n"
1151 "#endif\n"
1152 "\n"
1153 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPRECT\n"
1156 "# ifdef USESHADOWSAMPLER\n"
1157 "uniform sampler2DRectShadow Texture_ShadowMapRect;\n"
1158 "# else\n"
1159 "uniform sampler2DRect Texture_ShadowMapRect;\n"
1160 "# endif\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USESHADOWMAP2D\n"
1164 "# ifdef USESHADOWSAMPLER\n"
1165 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1166 "# else\n"
1167 "uniform sampler2D Texture_ShadowMap2D;\n"
1168 "# endif\n"
1169 "#endif\n"
1170 "\n"
1171 "#ifdef USESHADOWMAPVSDCT\n"
1172 "uniform samplerCube Texture_CubeProjection;\n"
1173 "#endif\n"
1174 "\n"
1175 "#ifdef USESHADOWMAPCUBE\n"
1176 "# ifdef USESHADOWSAMPLER\n"
1177 "uniform samplerCubeShadow Texture_ShadowMapCube;\n"
1178 "# else\n"
1179 "uniform samplerCube Texture_ShadowMapCube;\n"
1180 "# endif\n"
1181 "#endif\n"
1182 "\n"
1183 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
1184 "uniform vec2 ShadowMap_TextureScale;\n"
1185 "uniform vec4 ShadowMap_Parameters;\n"
1186 "#endif\n"
1187 "\n"
1188 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1189 "# ifdef USESHADOWMAPORTHO\n"
1190 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1191 "# else\n"
1192 "#  ifdef USESHADOWMAPVSDCT\n"
1193 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1194 "{\n"
1195 "       vec3 adir = abs(dir);\n"
1196 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1197 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1198 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1199 "}\n"
1200 "#  else\n"
1201 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1202 "{\n"
1203 "       vec3 adir = abs(dir);\n"
1204 "       float ma = adir.z;\n"
1205 "       vec4 proj = vec4(dir, 2.5);\n"
1206 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1207 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1209 "       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"
1210 "}\n"
1211 "#  endif\n"
1212 "# endif\n"
1213 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAPCUBE\n"
1216 "vec4 GetShadowMapTCCube(vec3 dir)\n"
1217 "{\n"
1218 "       vec3 adir = abs(dir);\n"
1219 "       return vec4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
1220 "}\n"
1221 "#endif\n"
1222 "\n"
1223 "# ifdef USESHADOWMAPRECT\n"
1224 "float ShadowMapCompare(vec3 dir)\n"
1225 "{\n"
1226 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1227 "       float f;\n"
1228 "#  ifdef USESHADOWSAMPLER\n"
1229 "\n"
1230 "#    ifdef USESHADOWMAPPCF\n"
1231 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + vec3(x, y, 0.0)).r\n"
1232 "       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"
1233 "#    else\n"
1234 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
1235 "#    endif\n"
1236 "\n"
1237 "#  else\n"
1238 "\n"
1239 "#    ifdef USESHADOWMAPPCF\n"
1240 "#      if USESHADOWMAPPCF > 1\n"
1241 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, center + vec2(x, y)).r\n"
1242 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1243 "       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"
1244 "       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"
1245 "       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"
1246 "       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"
1247 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1248 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1249 "#      else\n"
1250 "#        define texval(x, y) texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy + vec2(x, y)).r\n"
1251 "       vec2 offset = fract(shadowmaptc.xy);\n"
1252 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1253 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1254 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1255 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1256 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1257 "#      endif\n"
1258 "#    else\n"
1259 "       f = step(shadowmaptc.z, texture2DRect(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
1260 "#    endif\n"
1261 "\n"
1262 "#  endif\n"
1263 "#  ifdef USESHADOWMAPORTHO\n"
1264 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1265 "#  else\n"
1266 "       return f;\n"
1267 "#  endif\n"
1268 "}\n"
1269 "# endif\n"
1270 "\n"
1271 "# ifdef USESHADOWMAP2D\n"
1272 "float ShadowMapCompare(vec3 dir)\n"
1273 "{\n"
1274 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1275 "       float f;\n"
1276 "\n"
1277 "#  ifdef USESHADOWSAMPLER\n"
1278 "#    ifdef USESHADOWMAPPCF\n"
1279 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1280 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1281 "       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"
1282 "#    else\n"
1283 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1284 "#    endif\n"
1285 "#  else\n"
1286 "#    ifdef USESHADOWMAPPCF\n"
1287 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1288 "#      ifdef GL_ARB_texture_gather\n"
1289 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1290 "#      else\n"
1291 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1292 "#      endif\n"
1293 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1294 "#      if USESHADOWMAPPCF > 1\n"
1295 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1296 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1297 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1298 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1299 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1300 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1301 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1302 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1303 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1304 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1305 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1306 "       locols.yz += group2.ab;\n"
1307 "       hicols.yz += group8.rg;\n"
1308 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1309 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1310 "                               mix(locols, hicols, offset.y);\n"
1311 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1312 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1313 "       f = dot(cols, vec4(1.0/25.0));\n"
1314 "#      else\n"
1315 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1316 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1317 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1318 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1319 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1320 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1321 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1322 "#      endif\n"
1323 "#     else\n"
1324 "#      ifdef GL_EXT_gpu_shader4\n"
1325 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1326 "#      else\n"
1327 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1328 "#      endif\n"
1329 "#      if USESHADOWMAPPCF > 1\n"
1330 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1331 "       center *= ShadowMap_TextureScale;\n"
1332 "       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"
1333 "       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"
1334 "       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"
1335 "       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"
1336 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1337 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1338 "#      else\n"
1339 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1340 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1341 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1342 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1343 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1344 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1345 "#      endif\n"
1346 "#     endif\n"
1347 "#    else\n"
1348 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1349 "#    endif\n"
1350 "#  endif\n"
1351 "#  ifdef USESHADOWMAPORTHO\n"
1352 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1353 "#  else\n"
1354 "       return f;\n"
1355 "#  endif\n"
1356 "}\n"
1357 "# endif\n"
1358 "\n"
1359 "# ifdef USESHADOWMAPCUBE\n"
1360 "float ShadowMapCompare(vec3 dir)\n"
1361 "{\n"
1362 "       // apply depth texture cubemap as light filter\n"
1363 "       vec4 shadowmaptc = GetShadowMapTCCube(dir);\n"
1364 "       float f;\n"
1365 "#  ifdef USESHADOWSAMPLER\n"
1366 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
1367 "#  else\n"
1368 "       f = step(shadowmaptc.w, textureCube(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
1369 "#  endif\n"
1370 "       return f;\n"
1371 "}\n"
1372 "# endif\n"
1373 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1374 "#endif // FRAGMENT_SHADER\n"
1375 "\n"
1376 "\n"
1377 "\n"
1378 "\n"
1379 "#ifdef MODE_DEFERREDGEOMETRY\n"
1380 "#ifdef VERTEX_SHADER\n"
1381 "uniform mat4 TexMatrix;\n"
1382 "#ifdef USEVERTEXTEXTUREBLEND\n"
1383 "uniform mat4 BackgroundTexMatrix;\n"
1384 "#endif\n"
1385 "uniform mat4 ModelViewMatrix;\n"
1386 "void main(void)\n"
1387 "{\n"
1388 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1389 "#ifdef USEVERTEXTEXTUREBLEND\n"
1390 "       gl_FrontColor = gl_Color;\n"
1391 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1392 "#endif\n"
1393 "\n"
1394 "       // transform unnormalized eye direction into tangent space\n"
1395 "#ifdef USEOFFSETMAPPING\n"
1396 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1397 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1398 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1399 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1400 "#endif\n"
1401 "\n"
1402 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1403 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1404 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1405 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1406 "}\n"
1407 "#endif // VERTEX_SHADER\n"
1408 "\n"
1409 "#ifdef FRAGMENT_SHADER\n"
1410 "void main(void)\n"
1411 "{\n"
1412 "#ifdef USEOFFSETMAPPING\n"
1413 "       // apply offsetmapping\n"
1414 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1415 "#define TexCoord TexCoordOffset\n"
1416 "#endif\n"
1417 "\n"
1418 "#ifdef USEALPHAKILL\n"
1419 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1420 "               discard;\n"
1421 "#endif\n"
1422 "\n"
1423 "#ifdef USEVERTEXTEXTUREBLEND\n"
1424 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1425 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1426 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1427 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1428 "#endif\n"
1429 "\n"
1430 "#ifdef USEVERTEXTEXTUREBLEND\n"
1431 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1432 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1433 "#else\n"
1434 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1435 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1436 "#endif\n"
1437 "\n"
1438 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1439 "}\n"
1440 "#endif // FRAGMENT_SHADER\n"
1441 "#else // !MODE_DEFERREDGEOMETRY\n"
1442 "\n"
1443 "\n"
1444 "\n"
1445 "\n"
1446 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1447 "#ifdef VERTEX_SHADER\n"
1448 "uniform mat4 ModelViewMatrix;\n"
1449 "void main(void)\n"
1450 "{\n"
1451 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1452 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1453 "}\n"
1454 "#endif // VERTEX_SHADER\n"
1455 "\n"
1456 "#ifdef FRAGMENT_SHADER\n"
1457 "uniform mat4 ViewToLight;\n"
1458 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1459 "uniform vec2 ScreenToDepth;\n"
1460 "uniform myhalf3 DeferredColor_Ambient;\n"
1461 "uniform myhalf3 DeferredColor_Diffuse;\n"
1462 "#ifdef USESPECULAR\n"
1463 "uniform myhalf3 DeferredColor_Specular;\n"
1464 "uniform myhalf SpecularPower;\n"
1465 "#endif\n"
1466 "uniform myhalf2 PixelToScreenTexCoord;\n"
1467 "void main(void)\n"
1468 "{\n"
1469 "       // calculate viewspace pixel position\n"
1470 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1471 "       vec3 position;\n"
1472 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1473 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1474 "       // decode viewspace pixel normal\n"
1475 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1476 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1477 "       // surfacenormal = pixel normal in viewspace\n"
1478 "       // LightVector = pixel to light in viewspace\n"
1479 "       // CubeVector = position in lightspace\n"
1480 "       // eyevector = pixel to view in viewspace\n"
1481 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1482 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1483 "#ifdef USEDIFFUSE\n"
1484 "       // calculate diffuse shading\n"
1485 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1486 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1487 "#endif\n"
1488 "#ifdef USESPECULAR\n"
1489 "       // calculate directional shading\n"
1490 "       vec3 eyevector = position * -1.0;\n"
1491 "#  ifdef USEEXACTSPECULARMATH\n"
1492 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1493 "#  else\n"
1494 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1495 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1496 "#  endif\n"
1497 "#endif\n"
1498 "\n"
1499 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1500 "       fade *= ShadowMapCompare(CubeVector);\n"
1501 "#endif\n"
1502 "\n"
1503 "#ifdef USEDIFFUSE\n"
1504 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1505 "#else\n"
1506 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1507 "#endif\n"
1508 "#ifdef USESPECULAR\n"
1509 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1510 "#else\n"
1511 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1512 "#endif\n"
1513 "\n"
1514 "# ifdef USECUBEFILTER\n"
1515 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1516 "       gl_FragData[0].rgb *= cubecolor;\n"
1517 "       gl_FragData[1].rgb *= cubecolor;\n"
1518 "# endif\n"
1519 "}\n"
1520 "#endif // FRAGMENT_SHADER\n"
1521 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1522 "\n"
1523 "\n"
1524 "\n"
1525 "\n"
1526 "#ifdef VERTEX_SHADER\n"
1527 "uniform mat4 TexMatrix;\n"
1528 "#ifdef USEVERTEXTEXTUREBLEND\n"
1529 "uniform mat4 BackgroundTexMatrix;\n"
1530 "#endif\n"
1531 "#ifdef MODE_LIGHTSOURCE\n"
1532 "uniform mat4 ModelToLight;\n"
1533 "#endif\n"
1534 "#ifdef USESHADOWMAPORTHO\n"
1535 "uniform mat4 ShadowMapMatrix;\n"
1536 "#endif\n"
1537 "void main(void)\n"
1538 "{\n"
1539 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1540 "       gl_FrontColor = gl_Color;\n"
1541 "#endif\n"
1542 "       // copy the surface texcoord\n"
1543 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1544 "#ifdef USEVERTEXTEXTUREBLEND\n"
1545 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1546 "#endif\n"
1547 "#ifdef USELIGHTMAP\n"
1548 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1549 "#endif\n"
1550 "\n"
1551 "#ifdef MODE_LIGHTSOURCE\n"
1552 "       // transform vertex position into light attenuation/cubemap space\n"
1553 "       // (-1 to +1 across the light box)\n"
1554 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1555 "\n"
1556 "# ifdef USEDIFFUSE\n"
1557 "       // transform unnormalized light direction into tangent space\n"
1558 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1559 "       //  normalize it per pixel)\n"
1560 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1561 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1562 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1563 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1564 "# endif\n"
1565 "#endif\n"
1566 "\n"
1567 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1568 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1569 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1570 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1571 "#endif\n"
1572 "\n"
1573 "       // transform unnormalized eye direction into tangent space\n"
1574 "#ifdef USEEYEVECTOR\n"
1575 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1576 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1577 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1578 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1579 "#endif\n"
1580 "\n"
1581 "#ifdef USEFOG\n"
1582 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1583 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1584 "#endif\n"
1585 "\n"
1586 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1587 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1588 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1589 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1590 "#endif\n"
1591 "\n"
1592 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1593 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1594 "\n"
1595 "#ifdef USESHADOWMAPORTHO\n"
1596 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1597 "#endif\n"
1598 "\n"
1599 "#ifdef USEREFLECTION\n"
1600 "       ModelViewProjectionPosition = gl_Position;\n"
1601 "#endif\n"
1602 "}\n"
1603 "#endif // VERTEX_SHADER\n"
1604 "\n"
1605 "\n"
1606 "\n"
1607 "\n"
1608 "#ifdef FRAGMENT_SHADER\n"
1609 "#ifdef USEDEFERREDLIGHTMAP\n"
1610 "uniform myhalf2 PixelToScreenTexCoord;\n"
1611 "uniform myhalf3 DeferredMod_Diffuse;\n"
1612 "uniform myhalf3 DeferredMod_Specular;\n"
1613 "#endif\n"
1614 "uniform myhalf3 Color_Ambient;\n"
1615 "uniform myhalf3 Color_Diffuse;\n"
1616 "uniform myhalf3 Color_Specular;\n"
1617 "uniform myhalf SpecularPower;\n"
1618 "#ifdef USEGLOW\n"
1619 "uniform myhalf3 Color_Glow;\n"
1620 "#endif\n"
1621 "uniform myhalf Alpha;\n"
1622 "#ifdef USEREFLECTION\n"
1623 "uniform vec4 DistortScaleRefractReflect;\n"
1624 "uniform vec4 ScreenScaleRefractReflect;\n"
1625 "uniform vec4 ScreenCenterRefractReflect;\n"
1626 "uniform myhalf4 ReflectColor;\n"
1627 "#endif\n"
1628 "#ifdef USEREFLECTCUBE\n"
1629 "uniform mat4 ModelToReflectCube;\n"
1630 "uniform sampler2D Texture_ReflectMask;\n"
1631 "uniform samplerCube Texture_ReflectCube;\n"
1632 "#endif\n"
1633 "#ifdef MODE_LIGHTDIRECTION\n"
1634 "uniform myhalf3 LightColor;\n"
1635 "#endif\n"
1636 "#ifdef MODE_LIGHTSOURCE\n"
1637 "uniform myhalf3 LightColor;\n"
1638 "#endif\n"
1639 "void main(void)\n"
1640 "{\n"
1641 "#ifdef USEOFFSETMAPPING\n"
1642 "       // apply offsetmapping\n"
1643 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1644 "#define TexCoord TexCoordOffset\n"
1645 "#endif\n"
1646 "\n"
1647 "       // combine the diffuse textures (base, pants, shirt)\n"
1648 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1649 "#ifdef USEALPHAKILL\n"
1650 "       if (color.a < 0.5)\n"
1651 "               discard;\n"
1652 "#endif\n"
1653 "       color.a *= Alpha;\n"
1654 "#ifdef USECOLORMAPPING\n"
1655 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1656 "#endif\n"
1657 "#ifdef USEVERTEXTEXTUREBLEND\n"
1658 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1659 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1660 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1661 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1662 "       color.a = 1.0;\n"
1663 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1664 "#endif\n"
1665 "\n"
1666 "       // get the surface normal\n"
1667 "#ifdef USEVERTEXTEXTUREBLEND\n"
1668 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1669 "#else\n"
1670 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1671 "#endif\n"
1672 "\n"
1673 "       // get the material colors\n"
1674 "       myhalf3 diffusetex = color.rgb;\n"
1675 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1676 "# ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1678 "# else\n"
1679 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1680 "# endif\n"
1681 "#endif\n"
1682 "\n"
1683 "#ifdef USEREFLECTCUBE\n"
1684 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1685 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1686 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1687 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1688 "#endif\n"
1689 "\n"
1690 "\n"
1691 "\n"
1692 "\n"
1693 "#ifdef MODE_LIGHTSOURCE\n"
1694 "       // light source\n"
1695 "#ifdef USEDIFFUSE\n"
1696 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1697 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1698 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1699 "#ifdef USESPECULAR\n"
1700 "#ifdef USEEXACTSPECULARMATH\n"
1701 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1702 "#else\n"
1703 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1704 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1705 "#endif\n"
1706 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1707 "#endif\n"
1708 "#else\n"
1709 "       color.rgb = diffusetex * Color_Ambient;\n"
1710 "#endif\n"
1711 "       color.rgb *= LightColor;\n"
1712 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1713 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
1714 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1715 "#endif\n"
1716 "# ifdef USECUBEFILTER\n"
1717 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1718 "# endif\n"
1719 "#endif // MODE_LIGHTSOURCE\n"
1720 "\n"
1721 "\n"
1722 "\n"
1723 "\n"
1724 "#ifdef MODE_LIGHTDIRECTION\n"
1725 "#define SHADING\n"
1726 "#ifdef USEDIFFUSE\n"
1727 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1728 "#endif\n"
1729 "#define lightcolor LightColor\n"
1730 "#endif // MODE_LIGHTDIRECTION\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1734 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "       // convert modelspace light vector to tangentspace\n"
1737 "       myhalf3 lightnormal;\n"
1738 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1739 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1740 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1741 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1742 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1743 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1744 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1745 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1746 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1747 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1748 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1749 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1750 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1751 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1752 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1753 "#define SHADING\n"
1754 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1755 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1756 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1757 "#endif\n"
1758 "\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "#ifdef MODE_LIGHTMAP\n"
1763 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1764 "#endif // MODE_LIGHTMAP\n"
1765 "#ifdef MODE_VERTEXCOLOR\n"
1766 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1767 "#endif // MODE_VERTEXCOLOR\n"
1768 "#ifdef MODE_FLATCOLOR\n"
1769 "       color.rgb = diffusetex * Color_Ambient;\n"
1770 "#endif // MODE_FLATCOLOR\n"
1771 "\n"
1772 "\n"
1773 "\n"
1774 "\n"
1775 "#ifdef SHADING\n"
1776 "# ifdef USEDIFFUSE\n"
1777 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1778 "#  ifdef USESPECULAR\n"
1779 "#   ifdef USEEXACTSPECULARMATH\n"
1780 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1781 "#   else\n"
1782 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1783 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1784 "#   endif\n"
1785 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1786 "#  else\n"
1787 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1788 "#  endif\n"
1789 "# else\n"
1790 "       color.rgb = diffusetex * Color_Ambient;\n"
1791 "# endif\n"
1792 "#endif\n"
1793 "\n"
1794 "#ifdef USESHADOWMAPORTHO\n"
1795 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1796 "#endif\n"
1797 "\n"
1798 "#ifdef USEDEFERREDLIGHTMAP\n"
1799 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1800 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1801 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEGLOW\n"
1805 "#ifdef USEVERTEXTEXTUREBLEND\n"
1806 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1807 "#else\n"
1808 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1809 "#endif\n"
1810 "#endif\n"
1811 "\n"
1812 "#ifdef USEFOG\n"
1813 "       color.rgb = FogVertex(color.rgb);\n"
1814 "#endif\n"
1815 "\n"
1816 "       // 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"
1817 "#ifdef USEREFLECTION\n"
1818 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1819 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1820 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1821 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1822 "       // FIXME temporary hack to detect the case that the reflection\n"
1823 "       // gets blackened at edges due to leaving the area that contains actual\n"
1824 "       // content.\n"
1825 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1826 "       // 'appening.\n"
1827 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1828 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1829 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1830 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1831 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1832 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1833 "#endif\n"
1834 "\n"
1835 "       gl_FragColor = vec4(color);\n"
1836 "}\n"
1837 "#endif // FRAGMENT_SHADER\n"
1838 "\n"
1839 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1840 "#endif // !MODE_DEFERREDGEOMETRY\n"
1841 "#endif // !MODE_WATER\n"
1842 "#endif // !MODE_REFRACTION\n"
1843 "#endif // !MODE_BLOOMBLUR\n"
1844 "#endif // !MODE_GENERIC\n"
1845 "#endif // !MODE_POSTPROCESS\n"
1846 "#endif // !MODE_SHOWDEPTH\n"
1847 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1848 ;
1849
1850 /*
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868
1869
1870
1871 =========================================================================================================================================================
1872
1873
1874
1875 =========================================================================================================================================================
1876 */
1877
1878 const char *builtincgshaderstring =
1879 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1880 "// written by Forest 'LordHavoc' Hale\n"
1881 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1882 "\n"
1883 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1884 "#if defined(USEREFLECTION)\n"
1885 "#undef USESHADOWMAPORTHO\n"
1886 "#endif\n"
1887 "\n"
1888 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1889 "# define USEFOG\n"
1890 "#endif\n"
1891 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1892 "#define USELIGHTMAP\n"
1893 "#endif\n"
1894 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1895 "#define USEEYEVECTOR\n"
1896 "#endif\n"
1897 "\n"
1898 "#ifdef FRAGMENT_SHADER\n"
1899 "#ifdef HLSL\n"
1900 "//#undef USESHADOWMAPPCF\n"
1901 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1902 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1903 "#else\n"
1904 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1905 "#endif\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1909 "#ifdef VERTEX_SHADER\n"
1910 "void main\n"
1911 "(\n"
1912 "float4 gl_Vertex : POSITION,\n"
1913 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1914 "out float4 gl_Position : POSITION,\n"
1915 "out float Depth : TEXCOORD0\n"
1916 ")\n"
1917 "{\n"
1918 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1919 "       Depth = gl_Position.z;\n"
1920 "}\n"
1921 "#endif\n"
1922 "\n"
1923 "#ifdef FRAGMENT_SHADER\n"
1924 "void main\n"
1925 "(\n"
1926 "float Depth : TEXCOORD0,\n"
1927 "out float4 gl_FragColor : COLOR\n"
1928 ")\n"
1929 "{\n"
1930 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1931 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1932 "       temp.yz -= floor(temp.yz);\n"
1933 "       gl_FragColor = float4(temp,0);\n"
1934 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1935 "}\n"
1936 "#endif\n"
1937 "#else // !MODE_DEPTH_ORSHADOW\n"
1938 "\n"
1939 "\n"
1940 "\n"
1941 "\n"
1942 "#ifdef MODE_SHOWDEPTH\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float4 gl_FrontColor : COLOR0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float4 gl_FrontColor : COLOR0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "       gl_FragColor = gl_FrontColor;\n"
1965 "}\n"
1966 "#endif\n"
1967 "#else // !MODE_SHOWDEPTH\n"
1968 "\n"
1969 "\n"
1970 "\n"
1971 "\n"
1972 "#ifdef MODE_POSTPROCESS\n"
1973 "\n"
1974 "#ifdef VERTEX_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_Vertex : POSITION,\n"
1978 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1979 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1980 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1981 "out float4 gl_Position : POSITION,\n"
1982 "out float2 TexCoord1 : TEXCOORD0,\n"
1983 "out float2 TexCoord2 : TEXCOORD1\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1988 "#ifdef USEBLOOM\n"
1989 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1990 "#endif\n"
1991 "}\n"
1992 "#endif\n"
1993 "\n"
1994 "#ifdef FRAGMENT_SHADER\n"
1995 "void main\n"
1996 "(\n"
1997 "float2 TexCoord1 : TEXCOORD0,\n"
1998 "float2 TexCoord2 : TEXCOORD1,\n"
1999 "uniform sampler Texture_First : register(s0),\n"
2000 "#ifdef USEBLOOM\n"
2001 "uniform sampler Texture_Second : register(s1),\n"
2002 "#endif\n"
2003 "#ifdef USEGAMMARAMPS\n"
2004 "uniform sampler Texture_GammaRamps : register(s2),\n"
2005 "#endif\n"
2006 "#ifdef USESATURATION\n"
2007 "uniform float Saturation : register(c30),\n"
2008 "#endif\n"
2009 "#ifdef USEVIEWTINT\n"
2010 "uniform float4 ViewTintColor : register(c41),\n"
2011 "#endif\n"
2012 "uniform float4 UserVec1 : register(c37),\n"
2013 "uniform float4 UserVec2 : register(c38),\n"
2014 "uniform float4 UserVec3 : register(c39),\n"
2015 "uniform float4 UserVec4 : register(c40),\n"
2016 "uniform float ClientTime : register(c2),\n"
2017 "uniform float2 PixelSize : register(c25),\n"
2018 "uniform float4 BloomColorSubtract : register(c43),\n"
2019 "out float4 gl_FragColor : COLOR\n"
2020 ")\n"
2021 "{\n"
2022 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2023 "#ifdef USEBLOOM\n"
2024 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2028 "#endif\n"
2029 "\n"
2030 "#ifdef USEPOSTPROCESSING\n"
2031 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2032 "// 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"
2033 "       float sobel = 1.0;\n"
2034 "       // float2 ts = textureSize(Texture_First, 0);\n"
2035 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2036 "       float2 px = PixelSize;\n"
2037 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2038 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2039 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2040 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2041 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2042 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2043 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2044 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2045 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2046 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2047 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2048 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2049 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2050 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2051 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2052 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2053 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2054 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2055 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2056 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2057 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2058 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2059 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2060 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2061 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2062 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2063 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2064 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2065 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2066 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2067 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2068 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2069 "#endif\n"
2070 "\n"
2071 "#ifdef USESATURATION\n"
2072 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2073 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2074 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2075 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "out float4 gl_FrontColor : COLOR,\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "out float2 TexCoord2 : TEXCOORD1\n"
2103 ")\n"
2104 "{\n"
2105 "#ifdef HLSL\n"
2106 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2107 "#else\n"
2108 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2109 "#endif\n"
2110 "#ifdef USEDIFFUSE\n"
2111 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2112 "#endif\n"
2113 "#ifdef USESPECULAR\n"
2114 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2115 "#endif\n"
2116 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2117 "}\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef FRAGMENT_SHADER\n"
2121 "\n"
2122 "void main\n"
2123 "(\n"
2124 "float4 gl_FrontColor : COLOR0,\n"
2125 "float2 TexCoord1 : TEXCOORD0,\n"
2126 "float2 TexCoord2 : TEXCOORD1,\n"
2127 "#ifdef USEDIFFUSE\n"
2128 "uniform sampler Texture_First : register(s0),\n"
2129 "#endif\n"
2130 "#ifdef USESPECULAR\n"
2131 "uniform sampler Texture_Second : register(s1),\n"
2132 "#endif\n"
2133 "out float4 gl_FragColor : COLOR\n"
2134 ")\n"
2135 "{\n"
2136 "       gl_FragColor = gl_FrontColor;\n"
2137 "#ifdef USEDIFFUSE\n"
2138 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2139 "#endif\n"
2140 "\n"
2141 "#ifdef USESPECULAR\n"
2142 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2143 "# ifdef USECOLORMAPPING\n"
2144 "       gl_FragColor *= tex2;\n"
2145 "# endif\n"
2146 "# ifdef USEGLOW\n"
2147 "       gl_FragColor += tex2;\n"
2148 "# endif\n"
2149 "# ifdef USEVERTEXTEXTUREBLEND\n"
2150 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2151 "# endif\n"
2152 "#endif\n"
2153 "}\n"
2154 "#endif\n"
2155 "#else // !MODE_GENERIC\n"
2156 "\n"
2157 "\n"
2158 "\n"
2159 "\n"
2160 "#ifdef MODE_BLOOMBLUR\n"
2161 "#ifdef VERTEX_SHADER\n"
2162 "void main\n"
2163 "(\n"
2164 "float4 gl_Vertex : POSITION,\n"
2165 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2166 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2167 "out float4 gl_Position : POSITION,\n"
2168 "out float2 TexCoord : TEXCOORD0\n"
2169 ")\n"
2170 "{\n"
2171 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2172 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2173 "}\n"
2174 "#endif\n"
2175 "\n"
2176 "#ifdef FRAGMENT_SHADER\n"
2177 "\n"
2178 "void main\n"
2179 "(\n"
2180 "float2 TexCoord : TEXCOORD0,\n"
2181 "uniform sampler Texture_First : register(s0),\n"
2182 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2183 "out float4 gl_FragColor : COLOR\n"
2184 ")\n"
2185 "{\n"
2186 "       int i;\n"
2187 "       float2 tc = TexCoord;\n"
2188 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2189 "       tc += BloomBlur_Parameters.xy;\n"
2190 "       for (i = 1;i < SAMPLES;i++)\n"
2191 "       {\n"
2192 "               color += tex2D(Texture_First, tc).rgb;\n"
2193 "               tc += BloomBlur_Parameters.xy;\n"
2194 "       }\n"
2195 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2196 "}\n"
2197 "#endif\n"
2198 "#else // !MODE_BLOOMBLUR\n"
2199 "#ifdef MODE_REFRACTION\n"
2200 "#ifdef VERTEX_SHADER\n"
2201 "void main\n"
2202 "(\n"
2203 "float4 gl_Vertex : POSITION,\n"
2204 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2205 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2206 "uniform float4x4 TexMatrix : register(c0),\n"
2207 "uniform float3 EyePosition : register(c24),\n"
2208 "out float4 gl_Position : POSITION,\n"
2209 "out float2 TexCoord : TEXCOORD0,\n"
2210 "out float3 EyeVector : TEXCOORD1,\n"
2211 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2212 ")\n"
2213 "{\n"
2214 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2215 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2216 "       ModelViewProjectionPosition = gl_Position;\n"
2217 "}\n"
2218 "#endif\n"
2219 "\n"
2220 "#ifdef FRAGMENT_SHADER\n"
2221 "void main\n"
2222 "(\n"
2223 "float2 TexCoord : TEXCOORD0,\n"
2224 "float3 EyeVector : TEXCOORD1,\n"
2225 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2226 "uniform sampler Texture_Normal : register(s0),\n"
2227 "uniform sampler Texture_Refraction : register(s3),\n"
2228 "uniform sampler Texture_Reflection : register(s7),\n"
2229 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2230 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2231 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2232 "uniform float4 RefractColor : register(c29),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2237 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2238 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2239 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2240 "       // FIXME temporary hack to detect the case that the reflection\n"
2241 "       // gets blackened at edges due to leaving the area that contains actual\n"
2242 "       // content.\n"
2243 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2244 "       // 'appening.\n"
2245 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2246 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2247 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2248 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2249 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2250 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2251 "}\n"
2252 "#endif\n"
2253 "#else // !MODE_REFRACTION\n"
2254 "\n"
2255 "\n"
2256 "\n"
2257 "\n"
2258 "#ifdef MODE_WATER\n"
2259 "#ifdef VERTEX_SHADER\n"
2260 "\n"
2261 "void main\n"
2262 "(\n"
2263 "float4 gl_Vertex : POSITION,\n"
2264 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2265 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2266 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2267 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2268 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2269 "uniform float4x4 TexMatrix : register(c0),\n"
2270 "uniform float3 EyePosition : register(c24),\n"
2271 "out float4 gl_Position : POSITION,\n"
2272 "out float2 TexCoord : TEXCOORD0,\n"
2273 "out float3 EyeVector : TEXCOORD1,\n"
2274 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2275 ")\n"
2276 "{\n"
2277 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2278 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2279 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2280 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2281 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2282 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2283 "       ModelViewProjectionPosition = gl_Position;\n"
2284 "}\n"
2285 "#endif\n"
2286 "\n"
2287 "#ifdef FRAGMENT_SHADER\n"
2288 "void main\n"
2289 "(\n"
2290 "float2 TexCoord : TEXCOORD0,\n"
2291 "float3 EyeVector : TEXCOORD1,\n"
2292 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2293 "uniform sampler Texture_Normal : register(s0),\n"
2294 "uniform sampler Texture_Refraction : register(s3),\n"
2295 "uniform sampler Texture_Reflection : register(s7),\n"
2296 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2297 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2298 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2299 "uniform float4 RefractColor : register(c29),\n"
2300 "uniform float4 ReflectColor : register(c26),\n"
2301 "uniform float ReflectFactor : register(c27),\n"
2302 "uniform float ReflectOffset : register(c28),\n"
2303 "out float4 gl_FragColor : COLOR\n"
2304 ")\n"
2305 "{\n"
2306 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2307 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2308 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2309 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2310 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2311 "       // FIXME temporary hack to detect the case that the reflection\n"
2312 "       // gets blackened at edges due to leaving the area that contains actual\n"
2313 "       // content.\n"
2314 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2315 "       // 'appening.\n"
2316 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2317 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2318 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2319 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2320 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2321 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2322 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2323 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2324 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2325 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2326 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2327 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2328 "}\n"
2329 "#endif\n"
2330 "#else // !MODE_WATER\n"
2331 "\n"
2332 "\n"
2333 "\n"
2334 "\n"
2335 "// 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"
2336 "\n"
2337 "// fragment shader specific:\n"
2338 "#ifdef FRAGMENT_SHADER\n"
2339 "\n"
2340 "#ifdef USEFOG\n"
2341 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2342 "{\n"
2343 "       float fogfrac;\n"
2344 "#ifdef USEFOGHEIGHTTEXTURE\n"
2345 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2346 "       fogfrac = fogheightpixel.a;\n"
2347 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2348 "#else\n"
2349 "# ifdef USEFOGOUTSIDE\n"
2350 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2351 "# else\n"
2352 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2353 "# endif\n"
2354 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2355 "#endif\n"
2356 "}\n"
2357 "#endif\n"
2358 "\n"
2359 "#ifdef USEOFFSETMAPPING\n"
2360 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2361 "{\n"
2362 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2363 "       // 14 sample relief mapping: linear search and then binary search\n"
2364 "       // this basically steps forward a small amount repeatedly until it finds\n"
2365 "       // itself inside solid, then jitters forward and back using decreasing\n"
2366 "       // amounts to find the impact\n"
2367 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2368 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2369 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2370 "       float3 RT = float3(TexCoord, 1);\n"
2371 "       OffsetVector *= 0.1;\n"
2372 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2373 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2374 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2375 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2376 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2377 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2378 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2379 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2382 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2383 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2384 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2385 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2386 "       return RT.xy;\n"
2387 "#else\n"
2388 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2389 "       // this basically moves forward the full distance, and then backs up based\n"
2390 "       // on height of samples\n"
2391 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2392 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2393 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2394 "       TexCoord += OffsetVector;\n"
2395 "       OffsetVector *= 0.333;\n"
2396 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2397 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2398 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2399 "       return TexCoord;\n"
2400 "#endif\n"
2401 "}\n"
2402 "#endif // USEOFFSETMAPPING\n"
2403 "\n"
2404 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2405 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2406 "# ifdef USESHADOWMAPORTHO\n"
2407 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2408 "# else\n"
2409 "#  ifdef USESHADOWMAPVSDCT\n"
2410 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2411 "{\n"
2412 "       float3 adir = abs(dir);\n"
2413 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2414 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2415 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2416 "}\n"
2417 "#  else\n"
2418 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2419 "{\n"
2420 "       float3 adir = abs(dir);\n"
2421 "       float ma = adir.z;\n"
2422 "       float4 proj = float4(dir, 2.5);\n"
2423 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2424 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2425 "#ifdef HLSL\n"
2426 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2427 "#else\n"
2428 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2429 "       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"
2430 "#endif\n"
2431 "}\n"
2432 "#  endif\n"
2433 "# endif\n"
2434 "#endif // defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D)\n"
2435 "\n"
2436 "#ifdef USESHADOWMAPCUBE\n"
2437 "float4 GetShadowMapTCCube(float3 dir, float4 ShadowMap_Parameters)\n"
2438 "{\n"
2439 "       float3 adir = abs(dir);\n"
2440 "       return float4(dir, ShadowMap_Parameters.w + ShadowMap_Parameters.y / max(max(adir.x, adir.y), adir.z));\n"
2441 "}\n"
2442 "#endif\n"
2443 "\n"
2444 "# ifdef USESHADOWMAPRECT\n"
2445 "#ifdef USESHADOWMAPVSDCT\n"
2446 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2447 "#else\n"
2448 "float ShadowMapCompare(float3 dir, samplerRECT Texture_ShadowMapRect, float4 ShadowMap_Parameters)\n"
2449 "#endif\n"
2450 "{\n"
2451 "#ifdef USESHADOWMAPVSDCT\n"
2452 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2453 "#else\n"
2454 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2455 "#endif\n"
2456 "       float f;\n"
2457 "#  ifdef USESHADOWSAMPLER\n"
2458 "\n"
2459 "#    ifdef USESHADOWMAPPCF\n"
2460 "#      define texval(x, y) shadow2DRect(Texture_ShadowMapRect, shadowmaptc + float3(x, y, 0.0)).r\n"
2461 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2462 "#    else\n"
2463 "       f = shadow2DRect(Texture_ShadowMapRect, shadowmaptc).r;\n"
2464 "#    endif\n"
2465 "\n"
2466 "#  else\n"
2467 "\n"
2468 "#    ifdef USESHADOWMAPPCF\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, center + float2(x, y)).r\n"
2471 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2472 "       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"
2473 "       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"
2474 "       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"
2475 "       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"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "#        define texval(x, y) texRECT(Texture_ShadowMapRect, shadowmaptc.xy + float2(x, y)).r\n"
2480 "       float2 offset = frac(shadowmaptc.xy);\n"
2481 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2482 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2483 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2484 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2485 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2486 "#      endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, texRECT(Texture_ShadowMapRect, shadowmaptc.xy).r);\n"
2489 "#    endif\n"
2490 "\n"
2491 "#  endif\n"
2492 "#  ifdef USESHADOWMAPORTHO\n"
2493 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2494 "#  else\n"
2495 "       return f;\n"
2496 "#  endif\n"
2497 "}\n"
2498 "# endif\n"
2499 "\n"
2500 "# ifdef USESHADOWMAP2D\n"
2501 "#ifdef USESHADOWMAPVSDCT\n"
2502 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2503 "#else\n"
2504 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2505 "#endif\n"
2506 "{\n"
2507 "#ifdef USESHADOWMAPVSDCT\n"
2508 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2509 "#else\n"
2510 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2511 "#endif\n"
2512 "       float f;\n"
2513 "\n"
2514 "#  ifdef USESHADOWSAMPLER\n"
2515 "#    ifdef USESHADOWMAPPCF\n"
2516 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2517 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2518 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2519 "#    else\n"
2520 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2521 "#    endif\n"
2522 "#  else\n"
2523 "#    ifdef USESHADOWMAPPCF\n"
2524 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2525 "#      ifdef GL_ARB_texture_gather\n"
2526 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2527 "#      else\n"
2528 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2529 "#      endif\n"
2530 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2531 "#      if USESHADOWMAPPCF > 1\n"
2532 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2533 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2534 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2535 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2536 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2537 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2538 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2539 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2540 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2541 "       float4 locols = float4(group1.ab, group3.ab);\n"
2542 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2543 "       locols.yz += group2.ab;\n"
2544 "       hicols.yz += group8.rg;\n"
2545 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2546 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2547 "                               lerp(locols, hicols, offset.y);\n"
2548 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2549 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2550 "       f = dot(cols, float4(1.0/25.0));\n"
2551 "#      else\n"
2552 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2553 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2554 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2555 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2556 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2557 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2558 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2559 "#      endif\n"
2560 "#     else\n"
2561 "#      ifdef GL_EXT_gpu_shader4\n"
2562 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2563 "#      else\n"
2564 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2565 "#      endif\n"
2566 "#      if USESHADOWMAPPCF > 1\n"
2567 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2568 "       center *= ShadowMap_TextureScale;\n"
2569 "       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"
2570 "       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"
2571 "       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"
2572 "       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"
2573 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2574 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2575 "#      else\n"
2576 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2577 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2578 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2579 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2580 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2581 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2582 "#      endif\n"
2583 "#     endif\n"
2584 "#    else\n"
2585 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2586 "#    endif\n"
2587 "#  endif\n"
2588 "#  ifdef USESHADOWMAPORTHO\n"
2589 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2590 "#  else\n"
2591 "       return f;\n"
2592 "#  endif\n"
2593 "}\n"
2594 "# endif\n"
2595 "\n"
2596 "# ifdef USESHADOWMAPCUBE\n"
2597 "float ShadowMapCompare(float3 dir, samplerCUBE Texture_ShadowMapCube, float4 ShadowMap_Parameters)\n"
2598 "{\n"
2599 "       // apply depth texture cubemap as light filter\n"
2600 "       float4 shadowmaptc = GetShadowMapTCCube(dir, ShadowMap_Parameters);\n"
2601 "       float f;\n"
2602 "#  ifdef USESHADOWSAMPLER\n"
2603 "       f = shadowCube(Texture_ShadowMapCube, shadowmaptc).r;\n"
2604 "#  else\n"
2605 "       f = step(shadowmaptc.w, texCUBE(Texture_ShadowMapCube, shadowmaptc.xyz).r);\n"
2606 "#  endif\n"
2607 "       return f;\n"
2608 "}\n"
2609 "# endif\n"
2610 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2611 "#endif // FRAGMENT_SHADER\n"
2612 "\n"
2613 "\n"
2614 "\n"
2615 "\n"
2616 "#ifdef MODE_DEFERREDGEOMETRY\n"
2617 "#ifdef VERTEX_SHADER\n"
2618 "void main\n"
2619 "(\n"
2620 "float4 gl_Vertex : POSITION,\n"
2621 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2622 "#ifdef USEVERTEXTEXTUREBLEND\n"
2623 "float4 gl_Color : COLOR0,\n"
2624 "#endif\n"
2625 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2626 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2627 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2628 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2629 "uniform float4x4 TexMatrix : register(c0),\n"
2630 "#ifdef USEVERTEXTEXTUREBLEND\n"
2631 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2632 "#endif\n"
2633 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2634 "#ifdef USEOFFSETMAPPING\n"
2635 "uniform float3 EyePosition : register(c24),\n"
2636 "#endif\n"
2637 "out float4 gl_Position : POSITION,\n"
2638 "out float4 gl_FrontColor : COLOR,\n"
2639 "out float4 TexCoordBoth : TEXCOORD0,\n"
2640 "#ifdef USEOFFSETMAPPING\n"
2641 "out float3 EyeVector : TEXCOORD2,\n"
2642 "#endif\n"
2643 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2644 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2645 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2646 ")\n"
2647 "{\n"
2648 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "#ifdef HLSL\n"
2651 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2652 "#else\n"
2653 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2654 "#endif\n"
2655 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2656 "#endif\n"
2657 "\n"
2658 "       // transform unnormalized eye direction into tangent space\n"
2659 "#ifdef USEOFFSETMAPPING\n"
2660 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2661 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2662 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2663 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2664 "#endif\n"
2665 "\n"
2666 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2667 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2668 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2669 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2670 "}\n"
2671 "#endif // VERTEX_SHADER\n"
2672 "\n"
2673 "#ifdef FRAGMENT_SHADER\n"
2674 "void main\n"
2675 "(\n"
2676 "float4 TexCoordBoth : TEXCOORD0,\n"
2677 "float3 EyeVector : TEXCOORD2,\n"
2678 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2679 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2680 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2681 "uniform sampler Texture_Normal : register(s0),\n"
2682 "#ifdef USEALPHAKILL\n"
2683 "uniform sampler Texture_Color : register(s1),\n"
2684 "#endif\n"
2685 "uniform sampler Texture_Gloss : register(s2),\n"
2686 "#ifdef USEVERTEXTEXTUREBLEND\n"
2687 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2688 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2689 "#endif\n"
2690 "#ifdef USEOFFSETMAPPING\n"
2691 "uniform float OffsetMapping_Scale : register(c24),\n"
2692 "#endif\n"
2693 "uniform half SpecularPower : register(c36),\n"
2694 "out float4 gl_FragColor : COLOR\n"
2695 ")\n"
2696 "{\n"
2697 "       float2 TexCoord = TexCoordBoth.xy;\n"
2698 "#ifdef USEOFFSETMAPPING\n"
2699 "       // apply offsetmapping\n"
2700 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2701 "#define TexCoord TexCoordOffset\n"
2702 "#endif\n"
2703 "\n"
2704 "#ifdef USEALPHAKILL\n"
2705 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2706 "               discard;\n"
2707 "#endif\n"
2708 "\n"
2709 "#ifdef USEVERTEXTEXTUREBLEND\n"
2710 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2711 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2712 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2713 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2714 "#endif\n"
2715 "\n"
2716 "#ifdef USEVERTEXTEXTUREBLEND\n"
2717 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2718 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2719 "#else\n"
2720 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2721 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2722 "#endif\n"
2723 "\n"
2724 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2725 "}\n"
2726 "#endif // FRAGMENT_SHADER\n"
2727 "#else // !MODE_DEFERREDGEOMETRY\n"
2728 "\n"
2729 "\n"
2730 "\n"
2731 "\n"
2732 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2733 "#ifdef VERTEX_SHADER\n"
2734 "void main\n"
2735 "(\n"
2736 "float4 gl_Vertex : POSITION,\n"
2737 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2738 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2739 "out float4 gl_Position : POSITION,\n"
2740 "out float4 ModelViewPosition : TEXCOORD0\n"
2741 ")\n"
2742 "{\n"
2743 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2744 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2745 "}\n"
2746 "#endif // VERTEX_SHADER\n"
2747 "\n"
2748 "#ifdef FRAGMENT_SHADER\n"
2749 "void main\n"
2750 "(\n"
2751 "#ifdef HLSL\n"
2752 "float2 Pixel : VPOS,\n"
2753 "#else\n"
2754 "float2 Pixel : WPOS,\n"
2755 "#endif\n"
2756 "float4 ModelViewPosition : TEXCOORD0,\n"
2757 "uniform float4x4 ViewToLight : register(c44),\n"
2758 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2759 "uniform float3 LightPosition : register(c23),\n"
2760 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2761 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2762 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2763 "#ifdef USESPECULAR\n"
2764 "uniform half3 DeferredColor_Specular : register(c11),\n"
2765 "uniform half SpecularPower : register(c36),\n"
2766 "#endif\n"
2767 "uniform sampler Texture_Attenuation : register(s9),\n"
2768 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2769 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2770 "\n"
2771 "#ifdef USECUBEFILTER\n"
2772 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2773 "#endif\n"
2774 "\n"
2775 "#ifdef USESHADOWMAPRECT\n"
2776 "# ifdef USESHADOWSAMPLER\n"
2777 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
2778 "# else\n"
2779 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#ifdef USESHADOWMAP2D\n"
2784 "# ifdef USESHADOWSAMPLER\n"
2785 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2786 "# else\n"
2787 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2788 "# endif\n"
2789 "#endif\n"
2790 "\n"
2791 "#ifdef USESHADOWMAPVSDCT\n"
2792 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2793 "#endif\n"
2794 "\n"
2795 "#ifdef USESHADOWMAPCUBE\n"
2796 "# ifdef USESHADOWSAMPLER\n"
2797 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
2798 "# else\n"
2799 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
2800 "# endif\n"
2801 "#endif\n"
2802 "\n"
2803 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
2804 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2805 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2806 "#endif\n"
2807 "\n"
2808 "out float4 gl_FragData0 : COLOR0,\n"
2809 "out float4 gl_FragData1 : COLOR1\n"
2810 ")\n"
2811 "{\n"
2812 "       // calculate viewspace pixel position\n"
2813 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2814 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2815 "       float3 position;\n"
2816 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2817 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2818 "       // decode viewspace pixel normal\n"
2819 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2820 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2821 "       // surfacenormal = pixel normal in viewspace\n"
2822 "       // LightVector = pixel to light in viewspace\n"
2823 "       // CubeVector = position in lightspace\n"
2824 "       // eyevector = pixel to view in viewspace\n"
2825 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2826 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2827 "#ifdef USEDIFFUSE\n"
2828 "       // calculate diffuse shading\n"
2829 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2830 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2831 "#endif\n"
2832 "#ifdef USESPECULAR\n"
2833 "       // calculate directional shading\n"
2834 "       float3 eyevector = position * -1.0;\n"
2835 "#  ifdef USEEXACTSPECULARMATH\n"
2836 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2837 "#  else\n"
2838 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2839 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2840 "#  endif\n"
2841 "#endif\n"
2842 "\n"
2843 "#if defined(USESHADOWMAP2D) || defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE)\n"
2844 "       fade *= ShadowMapCompare(CubeVector,\n"
2845 "# if defined(USESHADOWMAP2D)\n"
2846 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2847 "# endif\n"
2848 "# if defined(USESHADOWMAPRECT)\n"
2849 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
2850 "# endif\n"
2851 "# if defined(USESHADOWMAPCUBE)\n"
2852 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
2853 "# endif\n"
2854 "\n"
2855 "#ifdef USESHADOWMAPVSDCT\n"
2856 ", Texture_CubeProjection\n"
2857 "#endif\n"
2858 "       );\n"
2859 "#endif\n"
2860 "\n"
2861 "#ifdef USEDIFFUSE\n"
2862 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2863 "#else\n"
2864 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2865 "#endif\n"
2866 "#ifdef USESPECULAR\n"
2867 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2868 "#else\n"
2869 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2870 "#endif\n"
2871 "\n"
2872 "# ifdef USECUBEFILTER\n"
2873 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2874 "       gl_FragData0.rgb *= cubecolor;\n"
2875 "       gl_FragData1.rgb *= cubecolor;\n"
2876 "# endif\n"
2877 "}\n"
2878 "#endif // FRAGMENT_SHADER\n"
2879 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2880 "\n"
2881 "\n"
2882 "\n"
2883 "\n"
2884 "#ifdef VERTEX_SHADER\n"
2885 "void main\n"
2886 "(\n"
2887 "float4 gl_Vertex : POSITION,\n"
2888 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2889 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2890 "float4 gl_Color : COLOR0,\n"
2891 "#endif\n"
2892 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2893 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2894 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2895 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2896 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2897 "\n"
2898 "uniform float3 EyePosition : register(c24),\n"
2899 "uniform float4x4 TexMatrix : register(c0),\n"
2900 "#ifdef USEVERTEXTEXTUREBLEND\n"
2901 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2902 "#endif\n"
2903 "#ifdef MODE_LIGHTSOURCE\n"
2904 "uniform float4x4 ModelToLight : register(c20),\n"
2905 "#endif\n"
2906 "#ifdef MODE_LIGHTSOURCE\n"
2907 "uniform float3 LightPosition : register(c27),\n"
2908 "#endif\n"
2909 "#ifdef MODE_LIGHTDIRECTION\n"
2910 "uniform float3 LightDir : register(c26),\n"
2911 "#endif\n"
2912 "uniform float4 FogPlane : register(c25),\n"
2913 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2914 "uniform float3 LightPosition : register(c27),\n"
2915 "#endif\n"
2916 "#ifdef USESHADOWMAPORTHO\n"
2917 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2918 "#endif\n"
2919 "\n"
2920 "out float4 gl_FrontColor : COLOR,\n"
2921 "out float4 TexCoordBoth : TEXCOORD0,\n"
2922 "#ifdef USELIGHTMAP\n"
2923 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2924 "#endif\n"
2925 "#ifdef USEEYEVECTOR\n"
2926 "out float3 EyeVector : TEXCOORD2,\n"
2927 "#endif\n"
2928 "#ifdef USEREFLECTION\n"
2929 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2930 "#endif\n"
2931 "#ifdef USEFOG\n"
2932 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2933 "#endif\n"
2934 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2935 "out float3 LightVector : TEXCOORD1,\n"
2936 "#endif\n"
2937 "#ifdef MODE_LIGHTSOURCE\n"
2938 "out float3 CubeVector : TEXCOORD3,\n"
2939 "#endif\n"
2940 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2941 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2942 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2943 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2944 "#endif\n"
2945 "#ifdef USESHADOWMAPORTHO\n"
2946 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2947 "#endif\n"
2948 "out float4 gl_Position : POSITION\n"
2949 ")\n"
2950 "{\n"
2951 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2952 "#ifdef HLSL\n"
2953 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2954 "#else\n"
2955 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2956 "#endif\n"
2957 "#endif\n"
2958 "       // copy the surface texcoord\n"
2959 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2960 "#ifdef USEVERTEXTEXTUREBLEND\n"
2961 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2962 "#endif\n"
2963 "#ifdef USELIGHTMAP\n"
2964 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2965 "#endif\n"
2966 "\n"
2967 "#ifdef MODE_LIGHTSOURCE\n"
2968 "       // transform vertex position into light attenuation/cubemap space\n"
2969 "       // (-1 to +1 across the light box)\n"
2970 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2971 "\n"
2972 "# ifdef USEDIFFUSE\n"
2973 "       // transform unnormalized light direction into tangent space\n"
2974 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2975 "       //  normalize it per pixel)\n"
2976 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2977 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2978 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2979 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2980 "# endif\n"
2981 "#endif\n"
2982 "\n"
2983 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2984 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2985 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2986 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2987 "#endif\n"
2988 "\n"
2989 "       // transform unnormalized eye direction into tangent space\n"
2990 "#ifdef USEEYEVECTOR\n"
2991 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2992 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2993 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2994 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USEFOG\n"
2998 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2999 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
3000 "#endif\n"
3001 "\n"
3002 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3003 "       VectorS = gl_MultiTexCoord1.xyz;\n"
3004 "       VectorT = gl_MultiTexCoord2.xyz;\n"
3005 "       VectorR = gl_MultiTexCoord3.xyz;\n"
3006 "#endif\n"
3007 "\n"
3008 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
3009 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
3010 "\n"
3011 "#ifdef USESHADOWMAPORTHO\n"
3012 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
3013 "#endif\n"
3014 "\n"
3015 "#ifdef USEREFLECTION\n"
3016 "       ModelViewProjectionPosition = gl_Position;\n"
3017 "#endif\n"
3018 "}\n"
3019 "#endif // VERTEX_SHADER\n"
3020 "\n"
3021 "\n"
3022 "\n"
3023 "\n"
3024 "#ifdef FRAGMENT_SHADER\n"
3025 "void main\n"
3026 "(\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "#ifdef HLSL\n"
3029 "float2 Pixel : VPOS,\n"
3030 "#else\n"
3031 "float2 Pixel : WPOS,\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "float4 gl_FrontColor : COLOR,\n"
3035 "float4 TexCoordBoth : TEXCOORD0,\n"
3036 "#ifdef USELIGHTMAP\n"
3037 "float2 TexCoordLightmap : TEXCOORD1,\n"
3038 "#endif\n"
3039 "#ifdef USEEYEVECTOR\n"
3040 "float3 EyeVector : TEXCOORD2,\n"
3041 "#endif\n"
3042 "#ifdef USEREFLECTION\n"
3043 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3044 "#endif\n"
3045 "#ifdef USEFOG\n"
3046 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3047 "#endif\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3049 "float3 LightVector : TEXCOORD1,\n"
3050 "#endif\n"
3051 "#ifdef MODE_LIGHTSOURCE\n"
3052 "float3 CubeVector : TEXCOORD3,\n"
3053 "#endif\n"
3054 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3055 "float4 ModelViewPosition : TEXCOORD0,\n"
3056 "#endif\n"
3057 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3058 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3059 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3060 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3061 "#endif\n"
3062 "#ifdef USESHADOWMAPORTHO\n"
3063 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3064 "#endif\n"
3065 "\n"
3066 "uniform sampler Texture_Normal : register(s0),\n"
3067 "uniform sampler Texture_Color : register(s1),\n"
3068 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3069 "uniform sampler Texture_Gloss : register(s2),\n"
3070 "#endif\n"
3071 "#ifdef USEGLOW\n"
3072 "uniform sampler Texture_Glow : register(s3),\n"
3073 "#endif\n"
3074 "#ifdef USEVERTEXTEXTUREBLEND\n"
3075 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3076 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3077 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3078 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3079 "#endif\n"
3080 "#ifdef USEGLOW\n"
3081 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3082 "#endif\n"
3083 "#endif\n"
3084 "#ifdef USECOLORMAPPING\n"
3085 "uniform sampler Texture_Pants : register(s4),\n"
3086 "uniform sampler Texture_Shirt : register(s7),\n"
3087 "#endif\n"
3088 "#ifdef USEFOG\n"
3089 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3090 "uniform sampler Texture_FogMask : register(s8),\n"
3091 "#endif\n"
3092 "#ifdef USELIGHTMAP\n"
3093 "uniform sampler Texture_Lightmap : register(s9),\n"
3094 "#endif\n"
3095 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3096 "uniform sampler Texture_Deluxemap : register(s10),\n"
3097 "#endif\n"
3098 "#ifdef USEREFLECTION\n"
3099 "uniform sampler Texture_Reflection : register(s7),\n"
3100 "#endif\n"
3101 "\n"
3102 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3103 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3104 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3105 "#endif\n"
3106 "#ifdef USEDEFERREDLIGHTMAP\n"
3107 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3108 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3109 "#endif\n"
3110 "\n"
3111 "#ifdef USECOLORMAPPING\n"
3112 "uniform half3 Color_Pants : register(c7),\n"
3113 "uniform half3 Color_Shirt : register(c8),\n"
3114 "#endif\n"
3115 "#ifdef USEFOG\n"
3116 "uniform float3 FogColor : register(c16),\n"
3117 "uniform float FogRangeRecip : register(c20),\n"
3118 "uniform float FogPlaneViewDist : register(c19),\n"
3119 "uniform float FogHeightFade : register(c17),\n"
3120 "#endif\n"
3121 "\n"
3122 "#ifdef USEOFFSETMAPPING\n"
3123 "uniform float OffsetMapping_Scale : register(c24),\n"
3124 "#endif\n"
3125 "\n"
3126 "#ifdef USEDEFERREDLIGHTMAP\n"
3127 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3128 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3129 "uniform half3 DeferredMod_Specular : register(c13),\n"
3130 "#endif\n"
3131 "uniform half3 Color_Ambient : register(c3),\n"
3132 "uniform half3 Color_Diffuse : register(c4),\n"
3133 "uniform half3 Color_Specular : register(c5),\n"
3134 "uniform half SpecularPower : register(c36),\n"
3135 "#ifdef USEGLOW\n"
3136 "uniform half3 Color_Glow : register(c6),\n"
3137 "#endif\n"
3138 "uniform half Alpha : register(c0),\n"
3139 "#ifdef USEREFLECTION\n"
3140 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3141 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3142 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3143 "uniform half4 ReflectColor : register(c26),\n"
3144 "#endif\n"
3145 "#ifdef USEREFLECTCUBE\n"
3146 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3147 "uniform sampler Texture_ReflectMask : register(s5),\n"
3148 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3149 "#endif\n"
3150 "#ifdef MODE_LIGHTDIRECTION\n"
3151 "uniform half3 LightColor : register(c21),\n"
3152 "#endif\n"
3153 "#ifdef MODE_LIGHTSOURCE\n"
3154 "uniform half3 LightColor : register(c21),\n"
3155 "#endif\n"
3156 "\n"
3157 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3158 "uniform sampler Texture_Attenuation : register(s9),\n"
3159 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3160 "#endif\n"
3161 "\n"
3162 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3163 "\n"
3164 "#ifdef USESHADOWMAPRECT\n"
3165 "# ifdef USESHADOWSAMPLER\n"
3166 "uniform samplerRECTShadow Texture_ShadowMapRect : register(s11),\n"
3167 "# else\n"
3168 "uniform samplerRECT Texture_ShadowMapRect : register(s11),\n"
3169 "# endif\n"
3170 "#endif\n"
3171 "\n"
3172 "#ifdef USESHADOWMAP2D\n"
3173 "# ifdef USESHADOWSAMPLER\n"
3174 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3175 "# else\n"
3176 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
3177 "# endif\n"
3178 "#endif\n"
3179 "\n"
3180 "#ifdef USESHADOWMAPVSDCT\n"
3181 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3182 "#endif\n"
3183 "\n"
3184 "#ifdef USESHADOWMAPCUBE\n"
3185 "# ifdef USESHADOWSAMPLER\n"
3186 "uniform samplerCUBEShadow Texture_ShadowMapCube : register(s11),\n"
3187 "# else\n"
3188 "uniform samplerCUBE Texture_ShadowMapCube : register(s11),\n"
3189 "# endif\n"
3190 "#endif\n"
3191 "\n"
3192 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAP2D) || defined(USESHADOWMAPCUBE)\n"
3193 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3194 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3195 "#endif\n"
3196 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3197 "\n"
3198 "out float4 gl_FragColor : COLOR\n"
3199 ")\n"
3200 "{\n"
3201 "       float2 TexCoord = TexCoordBoth.xy;\n"
3202 "#ifdef USEVERTEXTEXTUREBLEND\n"
3203 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3204 "#endif\n"
3205 "#ifdef USEOFFSETMAPPING\n"
3206 "       // apply offsetmapping\n"
3207 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3208 "#define TexCoord TexCoordOffset\n"
3209 "#endif\n"
3210 "\n"
3211 "       // combine the diffuse textures (base, pants, shirt)\n"
3212 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3213 "#ifdef USEALPHAKILL\n"
3214 "       if (color.a < 0.5)\n"
3215 "               discard;\n"
3216 "#endif\n"
3217 "       color.a *= Alpha;\n"
3218 "#ifdef USECOLORMAPPING\n"
3219 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3220 "#endif\n"
3221 "#ifdef USEVERTEXTEXTUREBLEND\n"
3222 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3223 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3224 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3225 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3226 "       color.a = 1.0;\n"
3227 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3228 "#endif\n"
3229 "\n"
3230 "       // get the surface normal\n"
3231 "#ifdef USEVERTEXTEXTUREBLEND\n"
3232 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3233 "#else\n"
3234 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3235 "#endif\n"
3236 "\n"
3237 "       // get the material colors\n"
3238 "       half3 diffusetex = color.rgb;\n"
3239 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3240 "# ifdef USEVERTEXTEXTUREBLEND\n"
3241 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3242 "# else\n"
3243 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3244 "# endif\n"
3245 "#endif\n"
3246 "\n"
3247 "#ifdef USEREFLECTCUBE\n"
3248 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3249 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3250 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3251 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3252 "#endif\n"
3253 "\n"
3254 "\n"
3255 "\n"
3256 "\n"
3257 "#ifdef MODE_LIGHTSOURCE\n"
3258 "       // light source\n"
3259 "#ifdef USEDIFFUSE\n"
3260 "       half3 lightnormal = half3(normalize(LightVector));\n"
3261 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3262 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3263 "#ifdef USESPECULAR\n"
3264 "#ifdef USEEXACTSPECULARMATH\n"
3265 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3266 "#else\n"
3267 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3268 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3269 "#endif\n"
3270 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3271 "#endif\n"
3272 "#else\n"
3273 "       color.rgb = diffusetex * Color_Ambient;\n"
3274 "#endif\n"
3275 "       color.rgb *= LightColor;\n"
3276 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3277 "#if defined(USESHADOWMAPRECT) || defined(USESHADOWMAPCUBE) || defined(USESHADOWMAP2D)\n"
3278 "       color.rgb *= half(ShadowMapCompare(CubeVector,\n"
3279 "# if defined(USESHADOWMAP2D)\n"
3280 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3281 "# endif\n"
3282 "# if defined(USESHADOWMAPRECT)\n"
3283 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3284 "# endif\n"
3285 "# if defined(USESHADOWMAPCUBE)\n"
3286 "Texture_ShadowMapCube, ShadowMap_Parameters\n"
3287 "# endif\n"
3288 "\n"
3289 "#ifdef USESHADOWMAPVSDCT\n"
3290 ", Texture_CubeProjection\n"
3291 "#endif\n"
3292 "       ));\n"
3293 "\n"
3294 "#endif\n"
3295 "# ifdef USECUBEFILTER\n"
3296 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3297 "# endif\n"
3298 "\n"
3299 "#ifdef USESHADOWMAP2D\n"
3300 "#ifdef USESHADOWMAPVSDCT\n"
3301 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3302 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3303 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3304 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3305 "#else\n"
3306 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3307 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3308 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3309 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3310 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3311 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3312 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3313 "//     color.r = half(shadowmaptc.z);\n"
3314 "#endif\n"
3315 "//     color.r = 1;\n"
3316 "#endif\n"
3317 "//     color.rgb = half3(1,1,1);\n"
3318 "#endif // MODE_LIGHTSOURCE\n"
3319 "\n"
3320 "\n"
3321 "\n"
3322 "\n"
3323 "#ifdef MODE_LIGHTDIRECTION\n"
3324 "#define SHADING\n"
3325 "#ifdef USEDIFFUSE\n"
3326 "       half3 lightnormal = half3(normalize(LightVector));\n"
3327 "#endif\n"
3328 "#define lightcolor LightColor\n"
3329 "#endif // MODE_LIGHTDIRECTION\n"
3330 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3331 "#define SHADING\n"
3332 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3333 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3334 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3335 "       // convert modelspace light vector to tangentspace\n"
3336 "       half3 lightnormal;\n"
3337 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3338 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3339 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3340 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3341 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3342 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3343 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3344 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3345 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3346 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3347 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3348 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3349 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3350 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3351 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3352 "#define SHADING\n"
3353 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3354 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3355 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3356 "#endif\n"
3357 "\n"
3358 "\n"
3359 "\n"
3360 "\n"
3361 "#ifdef MODE_LIGHTMAP\n"
3362 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3363 "#endif // MODE_LIGHTMAP\n"
3364 "#ifdef MODE_VERTEXCOLOR\n"
3365 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3366 "#endif // MODE_VERTEXCOLOR\n"
3367 "#ifdef MODE_FLATCOLOR\n"
3368 "       color.rgb = diffusetex * Color_Ambient;\n"
3369 "#endif // MODE_FLATCOLOR\n"
3370 "\n"
3371 "\n"
3372 "\n"
3373 "\n"
3374 "#ifdef SHADING\n"
3375 "# ifdef USEDIFFUSE\n"
3376 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3377 "#  ifdef USESPECULAR\n"
3378 "#   ifdef USEEXACTSPECULARMATH\n"
3379 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3380 "#   else\n"
3381 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3382 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3383 "#   endif\n"
3384 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3385 "#  else\n"
3386 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3387 "#  endif\n"
3388 "# else\n"
3389 "       color.rgb = diffusetex * Color_Ambient;\n"
3390 "# endif\n"
3391 "#endif\n"
3392 "\n"
3393 "#ifdef USESHADOWMAPORTHO\n"
3394 "       color.rgb *= ShadowMapCompare(ShadowMapTC,\n"
3395 "# if defined(USESHADOWMAP2D)\n"
3396 "Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3397 "# endif\n"
3398 "# if defined(USESHADOWMAPRECT)\n"
3399 "Texture_ShadowMapRect, ShadowMap_Parameters\n"
3400 "# endif\n"
3401 "       );\n"
3402 "#endif\n"
3403 "\n"
3404 "#ifdef USEDEFERREDLIGHTMAP\n"
3405 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3406 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3407 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3408 "#endif\n"
3409 "\n"
3410 "#ifdef USEGLOW\n"
3411 "#ifdef USEVERTEXTEXTUREBLEND\n"
3412 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3413 "#else\n"
3414 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3415 "#endif\n"
3416 "#endif\n"
3417 "\n"
3418 "#ifdef USEFOG\n"
3419 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3420 "#endif\n"
3421 "\n"
3422 "       // 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"
3423 "#ifdef USEREFLECTION\n"
3424 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3425 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3426 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3427 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3428 "       // FIXME temporary hack to detect the case that the reflection\n"
3429 "       // gets blackened at edges due to leaving the area that contains actual\n"
3430 "       // content.\n"
3431 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3432 "       // 'appening.\n"
3433 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3434 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3435 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3436 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3437 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3438 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3439 "#endif\n"
3440 "\n"
3441 "       gl_FragColor = float4(color);\n"
3442 "}\n"
3443 "#endif // FRAGMENT_SHADER\n"
3444 "\n"
3445 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3446 "#endif // !MODE_DEFERREDGEOMETRY\n"
3447 "#endif // !MODE_WATER\n"
3448 "#endif // !MODE_REFRACTION\n"
3449 "#endif // !MODE_BLOOMBLUR\n"
3450 "#endif // !MODE_GENERIC\n"
3451 "#endif // !MODE_POSTPROCESS\n"
3452 "#endif // !MODE_SHOWDEPTH\n"
3453 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3454 ;
3455
3456 char *glslshaderstring = NULL;
3457 char *cgshaderstring = NULL;
3458 char *hlslshaderstring = NULL;
3459
3460 //=======================================================================================================================================================
3461
3462 typedef struct shaderpermutationinfo_s
3463 {
3464         const char *pretext;
3465         const char *name;
3466 }
3467 shaderpermutationinfo_t;
3468
3469 typedef struct shadermodeinfo_s
3470 {
3471         const char *vertexfilename;
3472         const char *geometryfilename;
3473         const char *fragmentfilename;
3474         const char *pretext;
3475         const char *name;
3476 }
3477 shadermodeinfo_t;
3478
3479 typedef enum shaderpermutation_e
3480 {
3481         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3482         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3483         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3484         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3485         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3486         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3487         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3488         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3489         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3490         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3491         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3492         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3493         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3494         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3495         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3496         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3497         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3498         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3499         SHADERPERMUTATION_SHADOWMAPRECT = 1<<18, ///< (lightsource) use shadowmap rectangle texture as light filter
3500         SHADERPERMUTATION_SHADOWMAPCUBE = 1<<19, ///< (lightsource) use shadowmap cubemap texture as light filter
3501         SHADERPERMUTATION_SHADOWMAP2D = 1<<20, ///< (lightsource) use shadowmap rectangle texture as light filter
3502         SHADERPERMUTATION_SHADOWMAPPCF = 1<<21, ///< (lightsource) use percentage closer filtering on shadowmap test results
3503         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<22, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3504         SHADERPERMUTATION_SHADOWSAMPLER = 1<<23, ///< (lightsource) use hardware shadowmap test
3505         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<24, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3506         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<25, //< (lightsource) use orthographic shadowmap projection
3507         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<26, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3508         SHADERPERMUTATION_ALPHAKILL = 1<<27, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3509         SHADERPERMUTATION_REFLECTCUBE = 1<<28, ///< fake reflections using global cubemap (not HDRI light probe)
3510         SHADERPERMUTATION_LIMIT = 1<<29, ///< size of permutations array
3511         SHADERPERMUTATION_COUNT = 29 ///< size of shaderpermutationinfo array
3512 }
3513 shaderpermutation_t;
3514
3515 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3516 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3517 {
3518         {"#define USEDIFFUSE\n", " diffuse"},
3519         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3520         {"#define USEVIEWTINT\n", " viewtint"},
3521         {"#define USECOLORMAPPING\n", " colormapping"},
3522         {"#define USESATURATION\n", " saturation"},
3523         {"#define USEFOGINSIDE\n", " foginside"},
3524         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3525         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3526         {"#define USEGAMMARAMPS\n", " gammaramps"},
3527         {"#define USECUBEFILTER\n", " cubefilter"},
3528         {"#define USEGLOW\n", " glow"},
3529         {"#define USEBLOOM\n", " bloom"},
3530         {"#define USESPECULAR\n", " specular"},
3531         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3532         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3533         {"#define USEREFLECTION\n", " reflection"},
3534         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3535         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3536         {"#define USESHADOWMAPRECT\n", " shadowmaprect"},
3537         {"#define USESHADOWMAPCUBE\n", " shadowmapcube"},
3538         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3539         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3540         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3541         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3542         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3543         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3544         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3545         {"#define USEALPHAKILL\n", " alphakill"},
3546         {"#define USEREFLECTCUBE\n", " reflectcube"},
3547 };
3548
3549 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3550 typedef enum shadermode_e
3551 {
3552         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3553         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3554         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3555         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3556         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3557         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3558         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3559         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3560         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3561         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3562         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3563         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3564         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3565         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3566         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3567         SHADERMODE_COUNT
3568 }
3569 shadermode_t;
3570
3571 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3572 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3573 {
3574         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3575         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3576         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3577         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3578         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3579         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3580         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3581         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3582         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3583         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3584         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3585         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3586         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3587         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3588         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3589 };
3590
3591 #ifdef SUPPORTCG
3592 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3593 {
3594         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3595         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3596         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3597         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3598         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3599         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3600         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3601         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3602         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3603         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3604         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3605         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3606         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3607         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3608         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3609 };
3610 #endif
3611
3612 #ifdef SUPPORTD3D
3613 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3614 {
3615         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3616         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3617         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3618         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3619         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3620         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3621         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3622         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3623         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3624         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3625         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3626         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3627         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3628         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3629         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3630 };
3631 #endif
3632
3633 struct r_glsl_permutation_s;
3634 typedef struct r_glsl_permutation_s
3635 {
3636         /// hash lookup data
3637         struct r_glsl_permutation_s *hashnext;
3638         unsigned int mode;
3639         unsigned int permutation;
3640
3641         /// indicates if we have tried compiling this permutation already
3642         qboolean compiled;
3643         /// 0 if compilation failed
3644         int program;
3645         /// locations of detected uniforms in program object, or -1 if not found
3646         int loc_Texture_First;
3647         int loc_Texture_Second;
3648         int loc_Texture_GammaRamps;
3649         int loc_Texture_Normal;
3650         int loc_Texture_Color;
3651         int loc_Texture_Gloss;
3652         int loc_Texture_Glow;
3653         int loc_Texture_SecondaryNormal;
3654         int loc_Texture_SecondaryColor;
3655         int loc_Texture_SecondaryGloss;
3656         int loc_Texture_SecondaryGlow;
3657         int loc_Texture_Pants;
3658         int loc_Texture_Shirt;
3659         int loc_Texture_FogHeightTexture;
3660         int loc_Texture_FogMask;
3661         int loc_Texture_Lightmap;
3662         int loc_Texture_Deluxemap;
3663         int loc_Texture_Attenuation;
3664         int loc_Texture_Cube;
3665         int loc_Texture_Refraction;
3666         int loc_Texture_Reflection;
3667         int loc_Texture_ShadowMapRect;
3668         int loc_Texture_ShadowMapCube;
3669         int loc_Texture_ShadowMap2D;
3670         int loc_Texture_CubeProjection;
3671         int loc_Texture_ScreenDepth;
3672         int loc_Texture_ScreenNormalMap;
3673         int loc_Texture_ScreenDiffuse;
3674         int loc_Texture_ScreenSpecular;
3675         int loc_Texture_ReflectMask;
3676         int loc_Texture_ReflectCube;
3677         int loc_Alpha;
3678         int loc_BloomBlur_Parameters;
3679         int loc_ClientTime;
3680         int loc_Color_Ambient;
3681         int loc_Color_Diffuse;
3682         int loc_Color_Specular;
3683         int loc_Color_Glow;
3684         int loc_Color_Pants;
3685         int loc_Color_Shirt;
3686         int loc_DeferredColor_Ambient;
3687         int loc_DeferredColor_Diffuse;
3688         int loc_DeferredColor_Specular;
3689         int loc_DeferredMod_Diffuse;
3690         int loc_DeferredMod_Specular;
3691         int loc_DistortScaleRefractReflect;
3692         int loc_EyePosition;
3693         int loc_FogColor;
3694         int loc_FogHeightFade;
3695         int loc_FogPlane;
3696         int loc_FogPlaneViewDist;
3697         int loc_FogRangeRecip;
3698         int loc_LightColor;
3699         int loc_LightDir;
3700         int loc_LightPosition;
3701         int loc_OffsetMapping_Scale;
3702         int loc_PixelSize;
3703         int loc_ReflectColor;
3704         int loc_ReflectFactor;
3705         int loc_ReflectOffset;
3706         int loc_RefractColor;
3707         int loc_Saturation;
3708         int loc_ScreenCenterRefractReflect;
3709         int loc_ScreenScaleRefractReflect;
3710         int loc_ScreenToDepth;
3711         int loc_ShadowMap_Parameters;
3712         int loc_ShadowMap_TextureScale;
3713         int loc_SpecularPower;
3714         int loc_UserVec1;
3715         int loc_UserVec2;
3716         int loc_UserVec3;
3717         int loc_UserVec4;
3718         int loc_ViewTintColor;
3719         int loc_ViewToLight;
3720         int loc_ModelToLight;
3721         int loc_TexMatrix;
3722         int loc_BackgroundTexMatrix;
3723         int loc_ModelViewProjectionMatrix;
3724         int loc_ModelViewMatrix;
3725         int loc_PixelToScreenTexCoord;
3726         int loc_ModelToReflectCube;
3727         int loc_ShadowMapMatrix;
3728         int loc_BloomColorSubtract;
3729 }
3730 r_glsl_permutation_t;
3731
3732 #define SHADERPERMUTATION_HASHSIZE 256
3733
3734 /// information about each possible shader permutation
3735 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3736 /// currently selected permutation
3737 r_glsl_permutation_t *r_glsl_permutation;
3738 /// storage for permutations linked in the hash table
3739 memexpandablearray_t r_glsl_permutationarray;
3740
3741 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3742 {
3743         //unsigned int hashdepth = 0;
3744         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3745         r_glsl_permutation_t *p;
3746         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3747         {
3748                 if (p->mode == mode && p->permutation == permutation)
3749                 {
3750                         //if (hashdepth > 10)
3751                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3752                         return p;
3753                 }
3754                 //hashdepth++;
3755         }
3756         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3757         p->mode = mode;
3758         p->permutation = permutation;
3759         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3760         r_glsl_permutationhash[mode][hashindex] = p;
3761         //if (hashdepth > 10)
3762         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3763         return p;
3764 }
3765
3766 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3767 {
3768         char *shaderstring;
3769         if (!filename || !filename[0])
3770                 return NULL;
3771         if (!strcmp(filename, "glsl/default.glsl"))
3772         {
3773                 if (!glslshaderstring)
3774                 {
3775                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3776                         if (glslshaderstring)
3777                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3778                         else
3779                                 glslshaderstring = (char *)builtinshaderstring;
3780                 }
3781                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3782                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3783                 return shaderstring;
3784         }
3785         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3786         if (shaderstring)
3787         {
3788                 if (printfromdisknotice)
3789                         Con_DPrintf("from disk %s... ", filename);
3790                 return shaderstring;
3791         }
3792         return shaderstring;
3793 }
3794
3795 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3796 {
3797         int i;
3798         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3799         int vertstrings_count = 0;
3800         int geomstrings_count = 0;
3801         int fragstrings_count = 0;
3802         char *vertexstring, *geometrystring, *fragmentstring;
3803         const char *vertstrings_list[32+3];
3804         const char *geomstrings_list[32+3];
3805         const char *fragstrings_list[32+3];
3806         char permutationname[256];
3807
3808         if (p->compiled)
3809                 return;
3810         p->compiled = true;
3811         p->program = 0;
3812
3813         permutationname[0] = 0;
3814         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3815         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3816         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3817
3818         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3819
3820         // the first pretext is which type of shader to compile as
3821         // (later these will all be bound together as a program object)
3822         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3823         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3824         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3825
3826         // the second pretext is the mode (for example a light source)
3827         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3828         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3829         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3830         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3831
3832         // now add all the permutation pretexts
3833         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3834         {
3835                 if (permutation & (1<<i))
3836                 {
3837                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3838                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3839                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3840                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3841                 }
3842                 else
3843                 {
3844                         // keep line numbers correct
3845                         vertstrings_list[vertstrings_count++] = "\n";
3846                         geomstrings_list[geomstrings_count++] = "\n";
3847                         fragstrings_list[fragstrings_count++] = "\n";
3848                 }
3849         }
3850
3851         // now append the shader text itself
3852         vertstrings_list[vertstrings_count++] = vertexstring;
3853         geomstrings_list[geomstrings_count++] = geometrystring;
3854         fragstrings_list[fragstrings_count++] = fragmentstring;
3855
3856         // if any sources were NULL, clear the respective list
3857         if (!vertexstring)
3858                 vertstrings_count = 0;
3859         if (!geometrystring)
3860                 geomstrings_count = 0;
3861         if (!fragmentstring)
3862                 fragstrings_count = 0;
3863
3864         // compile the shader program
3865         if (vertstrings_count + geomstrings_count + fragstrings_count)
3866                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3867         if (p->program)
3868         {
3869                 CHECKGLERROR
3870                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3871                 // look up all the uniform variable names we care about, so we don't
3872                 // have to look them up every time we set them
3873
3874                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3875                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3876                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3877                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3878                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3879                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3880                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3881                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3882                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3883                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3884                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3885                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3886                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3887                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3888                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3889                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3890                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3891                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3892                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3893                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3894                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3895                 p->loc_Texture_ShadowMapRect      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapRect");
3896                 p->loc_Texture_ShadowMapCube      = qglGetUniformLocationARB(p->program, "Texture_ShadowMapCube");
3897                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3898                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3899                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3900                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3901                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3902                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3903                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3904                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3905                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3906                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3907                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3908                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3909                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3910                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3911                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3912                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3913                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3914                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3915                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3916                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3917                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3918                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3919                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3920                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3921                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3922                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3923                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3924                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3925                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3926                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3927                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3928                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3929                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3930                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3931                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3932                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3933                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3934                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3935                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3936                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3937                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3938                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3939                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3940                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3941                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3942                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3943                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3944                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3945                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3946                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3947                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3948                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3949                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3950                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3951                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3952                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3953                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3954                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3955                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3956                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3957                 // initialize the samplers to refer to the texture units we use
3958                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3959                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3960                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3961                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3962                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3963                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3964                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3965                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3966                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3967                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3968                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3969                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3970                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3971                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3972                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3973                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3974                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3975                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3976                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3977                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3978                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3979                 if (p->loc_Texture_ShadowMapRect   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapRect  , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT);
3980                 if (p->loc_Texture_ShadowMapCube   >= 0) qglUniform1iARB(p->loc_Texture_ShadowMapCube  , GL20TU_SHADOWMAPCUBE);
3981                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3982                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3983                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3984                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3985                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3986                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3987                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3988                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3989                 CHECKGLERROR
3990                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3991         }
3992         else
3993                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3994
3995         // free the strings
3996         if (vertexstring)
3997                 Mem_Free(vertexstring);
3998         if (geometrystring)
3999                 Mem_Free(geometrystring);
4000         if (fragmentstring)
4001                 Mem_Free(fragmentstring);
4002 }
4003
4004 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4005 {
4006         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4007         if (r_glsl_permutation != perm)
4008         {
4009                 r_glsl_permutation = perm;
4010                 if (!r_glsl_permutation->program)
4011                 {
4012                         if (!r_glsl_permutation->compiled)
4013                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4014                         if (!r_glsl_permutation->program)
4015                         {
4016                                 // remove features until we find a valid permutation
4017                                 int i;
4018                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4019                                 {
4020                                         // reduce i more quickly whenever it would not remove any bits
4021                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4022                                         if (!(permutation & j))
4023                                                 continue;
4024                                         permutation -= j;
4025                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4026                                         if (!r_glsl_permutation->compiled)
4027                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4028                                         if (r_glsl_permutation->program)
4029                                                 break;
4030                                 }
4031                                 if (i >= SHADERPERMUTATION_COUNT)
4032                                 {
4033                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4034                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4035                                         qglUseProgramObjectARB(0);CHECKGLERROR
4036                                         return; // no bit left to clear, entire mode is broken
4037                                 }
4038                         }
4039                 }
4040                 CHECKGLERROR
4041                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
4042         }
4043         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4044         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4045         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
4046 }
4047
4048 #ifdef SUPPORTCG
4049 #include <Cg/cgGL.h>
4050 struct r_cg_permutation_s;
4051 typedef struct r_cg_permutation_s
4052 {
4053         /// hash lookup data
4054         struct r_cg_permutation_s *hashnext;
4055         unsigned int mode;
4056         unsigned int permutation;
4057
4058         /// indicates if we have tried compiling this permutation already
4059         qboolean compiled;
4060         /// 0 if compilation failed
4061         CGprogram vprogram;
4062         CGprogram fprogram;
4063         /// locations of detected parameters in programs, or NULL if not found
4064         CGparameter vp_EyePosition;
4065         CGparameter vp_FogPlane;
4066         CGparameter vp_LightDir;
4067         CGparameter vp_LightPosition;
4068         CGparameter vp_ModelToLight;
4069         CGparameter vp_TexMatrix;
4070         CGparameter vp_BackgroundTexMatrix;
4071         CGparameter vp_ModelViewProjectionMatrix;
4072         CGparameter vp_ModelViewMatrix;
4073         CGparameter vp_ShadowMapMatrix;
4074
4075         CGparameter fp_Texture_First;
4076         CGparameter fp_Texture_Second;
4077         CGparameter fp_Texture_GammaRamps;
4078         CGparameter fp_Texture_Normal;
4079         CGparameter fp_Texture_Color;
4080         CGparameter fp_Texture_Gloss;
4081         CGparameter fp_Texture_Glow;
4082         CGparameter fp_Texture_SecondaryNormal;
4083         CGparameter fp_Texture_SecondaryColor;
4084         CGparameter fp_Texture_SecondaryGloss;
4085         CGparameter fp_Texture_SecondaryGlow;
4086         CGparameter fp_Texture_Pants;
4087         CGparameter fp_Texture_Shirt;
4088         CGparameter fp_Texture_FogHeightTexture;
4089         CGparameter fp_Texture_FogMask;
4090         CGparameter fp_Texture_Lightmap;
4091         CGparameter fp_Texture_Deluxemap;
4092         CGparameter fp_Texture_Attenuation;
4093         CGparameter fp_Texture_Cube;
4094         CGparameter fp_Texture_Refraction;
4095         CGparameter fp_Texture_Reflection;
4096         CGparameter fp_Texture_ShadowMapRect;
4097         CGparameter fp_Texture_ShadowMapCube;
4098         CGparameter fp_Texture_ShadowMap2D;
4099         CGparameter fp_Texture_CubeProjection;
4100         CGparameter fp_Texture_ScreenDepth;
4101         CGparameter fp_Texture_ScreenNormalMap;
4102         CGparameter fp_Texture_ScreenDiffuse;
4103         CGparameter fp_Texture_ScreenSpecular;
4104         CGparameter fp_Texture_ReflectMask;
4105         CGparameter fp_Texture_ReflectCube;
4106         CGparameter fp_Alpha;
4107         CGparameter fp_BloomBlur_Parameters;
4108         CGparameter fp_ClientTime;
4109         CGparameter fp_Color_Ambient;
4110         CGparameter fp_Color_Diffuse;
4111         CGparameter fp_Color_Specular;
4112         CGparameter fp_Color_Glow;
4113         CGparameter fp_Color_Pants;
4114         CGparameter fp_Color_Shirt;
4115         CGparameter fp_DeferredColor_Ambient;
4116         CGparameter fp_DeferredColor_Diffuse;
4117         CGparameter fp_DeferredColor_Specular;
4118         CGparameter fp_DeferredMod_Diffuse;
4119         CGparameter fp_DeferredMod_Specular;
4120         CGparameter fp_DistortScaleRefractReflect;
4121         CGparameter fp_EyePosition;
4122         CGparameter fp_FogColor;
4123         CGparameter fp_FogHeightFade;
4124         CGparameter fp_FogPlane;
4125         CGparameter fp_FogPlaneViewDist;
4126         CGparameter fp_FogRangeRecip;
4127         CGparameter fp_LightColor;
4128         CGparameter fp_LightDir;
4129         CGparameter fp_LightPosition;
4130         CGparameter fp_OffsetMapping_Scale;
4131         CGparameter fp_PixelSize;
4132         CGparameter fp_ReflectColor;
4133         CGparameter fp_ReflectFactor;
4134         CGparameter fp_ReflectOffset;
4135         CGparameter fp_RefractColor;
4136         CGparameter fp_Saturation;
4137         CGparameter fp_ScreenCenterRefractReflect;
4138         CGparameter fp_ScreenScaleRefractReflect;
4139         CGparameter fp_ScreenToDepth;
4140         CGparameter fp_ShadowMap_Parameters;
4141         CGparameter fp_ShadowMap_TextureScale;
4142         CGparameter fp_SpecularPower;
4143         CGparameter fp_UserVec1;
4144         CGparameter fp_UserVec2;
4145         CGparameter fp_UserVec3;
4146         CGparameter fp_UserVec4;
4147         CGparameter fp_ViewTintColor;
4148         CGparameter fp_ViewToLight;
4149         CGparameter fp_PixelToScreenTexCoord;
4150         CGparameter fp_ModelToReflectCube;
4151         CGparameter fp_BloomColorSubtract;
4152 }
4153 r_cg_permutation_t;
4154
4155 /// information about each possible shader permutation
4156 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4157 /// currently selected permutation
4158 r_cg_permutation_t *r_cg_permutation;
4159 /// storage for permutations linked in the hash table
4160 memexpandablearray_t r_cg_permutationarray;
4161
4162 #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));}}
4163
4164 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4165 {
4166         //unsigned int hashdepth = 0;
4167         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4168         r_cg_permutation_t *p;
4169         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4170         {
4171                 if (p->mode == mode && p->permutation == permutation)
4172                 {
4173                         //if (hashdepth > 10)
4174                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4175                         return p;
4176                 }
4177                 //hashdepth++;
4178         }
4179         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4180         p->mode = mode;
4181         p->permutation = permutation;
4182         p->hashnext = r_cg_permutationhash[mode][hashindex];
4183         r_cg_permutationhash[mode][hashindex] = p;
4184         //if (hashdepth > 10)
4185         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4186         return p;
4187 }
4188
4189 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4190 {
4191         char *shaderstring;
4192         if (!filename || !filename[0])
4193                 return NULL;
4194         if (!strcmp(filename, "cg/default.cg"))
4195         {
4196                 if (!cgshaderstring)
4197                 {
4198                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4199                         if (cgshaderstring)
4200                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4201                         else
4202                                 cgshaderstring = (char *)builtincgshaderstring;
4203                 }
4204                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4205                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4206                 return shaderstring;
4207         }
4208         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4209         if (shaderstring)
4210         {
4211                 if (printfromdisknotice)
4212                         Con_DPrintf("from disk %s... ", filename);
4213                 return shaderstring;
4214         }
4215         return shaderstring;
4216 }
4217
4218 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4219 {
4220         // TODO: load or create .fp and .vp shader files
4221 }
4222
4223 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4224 {
4225         int i;
4226         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4227         int vertstrings_count = 0, vertstring_length = 0;
4228         int geomstrings_count = 0, geomstring_length = 0;
4229         int fragstrings_count = 0, fragstring_length = 0;
4230         char *t;
4231         char *vertexstring, *geometrystring, *fragmentstring;
4232         char *vertstring, *geomstring, *fragstring;
4233         const char *vertstrings_list[32+3];
4234         const char *geomstrings_list[32+3];
4235         const char *fragstrings_list[32+3];
4236         char permutationname[256];
4237         char cachename[256];
4238         CGprofile vertexProfile;
4239         CGprofile fragmentProfile;
4240
4241         if (p->compiled)
4242                 return;
4243         p->compiled = true;
4244         p->vprogram = NULL;
4245         p->fprogram = NULL;
4246
4247         permutationname[0] = 0;
4248         cachename[0] = 0;
4249         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4250         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4251         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4252
4253         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4254         strlcat(cachename, "cg/", sizeof(cachename));
4255
4256         // the first pretext is which type of shader to compile as
4257         // (later these will all be bound together as a program object)
4258         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4259         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4260         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4261
4262         // the second pretext is the mode (for example a light source)
4263         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4264         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4265         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4266         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4267         strlcat(cachename, modeinfo->name, sizeof(cachename));
4268
4269         // now add all the permutation pretexts
4270         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4271         {
4272                 if (permutation & (1<<i))
4273                 {
4274                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4275                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4276                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4277                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4278                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4279                 }
4280                 else
4281                 {
4282                         // keep line numbers correct
4283                         vertstrings_list[vertstrings_count++] = "\n";
4284                         geomstrings_list[geomstrings_count++] = "\n";
4285                         fragstrings_list[fragstrings_count++] = "\n";
4286                 }
4287         }
4288
4289         // replace spaces in the cachename with _ characters
4290         for (i = 0;cachename[i];i++)
4291                 if (cachename[i] == ' ')
4292                         cachename[i] = '_';
4293
4294         // now append the shader text itself
4295         vertstrings_list[vertstrings_count++] = vertexstring;
4296         geomstrings_list[geomstrings_count++] = geometrystring;
4297         fragstrings_list[fragstrings_count++] = fragmentstring;
4298
4299         // if any sources were NULL, clear the respective list
4300         if (!vertexstring)
4301                 vertstrings_count = 0;
4302         if (!geometrystring)
4303                 geomstrings_count = 0;
4304         if (!fragmentstring)
4305                 fragstrings_count = 0;
4306
4307         vertstring_length = 0;
4308         for (i = 0;i < vertstrings_count;i++)
4309                 vertstring_length += strlen(vertstrings_list[i]);
4310         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4311         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4312                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4313
4314         geomstring_length = 0;
4315         for (i = 0;i < geomstrings_count;i++)
4316                 geomstring_length += strlen(geomstrings_list[i]);
4317         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4318         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4319                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4320
4321         fragstring_length = 0;
4322         for (i = 0;i < fragstrings_count;i++)
4323                 fragstring_length += strlen(fragstrings_list[i]);
4324         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4325         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4326                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4327
4328         CHECKGLERROR
4329         CHECKCGERROR
4330         //vertexProfile = CG_PROFILE_ARBVP1;
4331         //fragmentProfile = CG_PROFILE_ARBFP1;
4332         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4333         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4334         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4335         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4336         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4337         CHECKGLERROR
4338
4339         // try to load the cached shader, or generate one
4340         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4341
4342         // if caching failed, do a dynamic compile for now
4343         CHECKCGERROR
4344         if (vertstring[0] && !p->vprogram)
4345                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4346         CHECKCGERROR
4347         if (fragstring[0] && !p->fprogram)
4348                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4349         CHECKCGERROR
4350
4351         // look up all the uniform variable names we care about, so we don't
4352         // have to look them up every time we set them
4353         if (p->vprogram)
4354         {
4355                 CHECKCGERROR
4356                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4357                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4358                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4359                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4360                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4361                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4362                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4363                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4364                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4365                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4366                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4367                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4368                 CHECKCGERROR
4369         }
4370         if (p->fprogram)
4371         {
4372                 CHECKCGERROR
4373                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4374                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4375                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4376                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4377                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4378                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4379                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4380                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4381                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4382                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4383                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4384                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4385                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4386                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4387                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4388                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4389                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4390                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4391                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4392                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4393                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4394                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4395                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4396                 p->fp_Texture_ShadowMapRect      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapRect");
4397                 p->fp_Texture_ShadowMapCube      = cgGetNamedParameter(p->fprogram, "Texture_ShadowMapCube");
4398                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4399                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4400                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4401                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4402                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4403                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4404                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4405                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4406                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4407                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4408                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4409                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4410                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4411                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4412                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4413                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4414                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4415                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4416                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4417                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4418                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4419                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4420                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4421                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4422                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4423                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4424                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4425                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4426                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4427                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4428                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4429                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4430                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4431                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4432                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4433                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4434                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4435                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4436                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4437                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4438                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4439                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4440                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4441                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4442                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4443                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4444                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4445                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4446                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4447                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4448                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4449                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4450                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4451                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4452                 CHECKCGERROR
4453         }
4454
4455         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4456                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4457         else
4458                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4459
4460         // free the strings
4461         if (vertstring)
4462                 Mem_Free(vertstring);
4463         if (geomstring)
4464                 Mem_Free(geomstring);
4465         if (fragstring)
4466                 Mem_Free(fragstring);
4467         if (vertexstring)
4468                 Mem_Free(vertexstring);
4469         if (geometrystring)
4470                 Mem_Free(geometrystring);
4471         if (fragmentstring)
4472                 Mem_Free(fragmentstring);
4473 }
4474
4475 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4476 {
4477         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4478         CHECKGLERROR
4479         CHECKCGERROR
4480         if (r_cg_permutation != perm)
4481         {
4482                 r_cg_permutation = perm;
4483                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4484                 {
4485                         if (!r_cg_permutation->compiled)
4486                                 R_CG_CompilePermutation(perm, mode, permutation);
4487                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4488                         {
4489                                 // remove features until we find a valid permutation
4490                                 int i;
4491                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4492                                 {
4493                                         // reduce i more quickly whenever it would not remove any bits
4494                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4495                                         if (!(permutation & j))
4496                                                 continue;
4497                                         permutation -= j;
4498                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4499                                         if (!r_cg_permutation->compiled)
4500                                                 R_CG_CompilePermutation(perm, mode, permutation);
4501                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4502                                                 break;
4503                                 }
4504                                 if (i >= SHADERPERMUTATION_COUNT)
4505                                 {
4506                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4507                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4508                                         return; // no bit left to clear, entire mode is broken
4509                                 }
4510                         }
4511                 }
4512                 CHECKGLERROR
4513                 CHECKCGERROR
4514                 if (r_cg_permutation->vprogram)
4515                 {
4516                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4517                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4518                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4519                 }
4520                 else
4521                 {
4522                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4523                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4524                 }
4525                 if (r_cg_permutation->fprogram)
4526                 {
4527                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4528                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4529                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4530                 }
4531                 else
4532                 {
4533                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4534                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4535                 }
4536         }
4537         CHECKCGERROR
4538         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4539         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4540         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4541 }
4542
4543 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4544 {
4545         cgGLSetTextureParameter(param, R_GetTexture(tex));
4546         cgGLEnableTextureParameter(param);
4547 }
4548 #endif
4549
4550 #ifdef SUPPORTD3D
4551
4552 #ifdef SUPPORTD3D
4553 #include <d3d9.h>
4554 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4555 extern D3DCAPS9 vid_d3d9caps;
4556 #endif
4557
4558 struct r_hlsl_permutation_s;
4559 typedef struct r_hlsl_permutation_s
4560 {
4561         /// hash lookup data
4562         struct r_hlsl_permutation_s *hashnext;
4563         unsigned int mode;
4564         unsigned int permutation;
4565
4566         /// indicates if we have tried compiling this permutation already
4567         qboolean compiled;
4568         /// NULL if compilation failed
4569         IDirect3DVertexShader9 *vertexshader;
4570         IDirect3DPixelShader9 *pixelshader;
4571 }
4572 r_hlsl_permutation_t;
4573
4574 typedef enum D3DVSREGISTER_e
4575 {
4576         D3DVSREGISTER_TexMatrix = 0, // float4x4
4577         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4578         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4579         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4580         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4581         D3DVSREGISTER_ModelToLight = 20, // float4x4
4582         D3DVSREGISTER_EyePosition = 24,
4583         D3DVSREGISTER_FogPlane = 25,
4584         D3DVSREGISTER_LightDir = 26,
4585         D3DVSREGISTER_LightPosition = 27,
4586 }
4587 D3DVSREGISTER_t;
4588
4589 typedef enum D3DPSREGISTER_e
4590 {
4591         D3DPSREGISTER_Alpha = 0,
4592         D3DPSREGISTER_BloomBlur_Parameters = 1,
4593         D3DPSREGISTER_ClientTime = 2,
4594         D3DPSREGISTER_Color_Ambient = 3,
4595         D3DPSREGISTER_Color_Diffuse = 4,
4596         D3DPSREGISTER_Color_Specular = 5,
4597         D3DPSREGISTER_Color_Glow = 6,
4598         D3DPSREGISTER_Color_Pants = 7,
4599         D3DPSREGISTER_Color_Shirt = 8,
4600         D3DPSREGISTER_DeferredColor_Ambient = 9,
4601         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4602         D3DPSREGISTER_DeferredColor_Specular = 11,
4603         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4604         D3DPSREGISTER_DeferredMod_Specular = 13,
4605         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4606         D3DPSREGISTER_EyePosition = 15, // unused
4607         D3DPSREGISTER_FogColor = 16,
4608         D3DPSREGISTER_FogHeightFade = 17,
4609         D3DPSREGISTER_FogPlane = 18,
4610         D3DPSREGISTER_FogPlaneViewDist = 19,
4611         D3DPSREGISTER_FogRangeRecip = 20,
4612         D3DPSREGISTER_LightColor = 21,
4613         D3DPSREGISTER_LightDir = 22, // unused
4614         D3DPSREGISTER_LightPosition = 23,
4615         D3DPSREGISTER_OffsetMapping_Scale = 24,
4616         D3DPSREGISTER_PixelSize = 25,
4617         D3DPSREGISTER_ReflectColor = 26,
4618         D3DPSREGISTER_ReflectFactor = 27,
4619         D3DPSREGISTER_ReflectOffset = 28,
4620         D3DPSREGISTER_RefractColor = 29,
4621         D3DPSREGISTER_Saturation = 30,
4622         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4623         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4624         D3DPSREGISTER_ScreenToDepth = 33,
4625         D3DPSREGISTER_ShadowMap_Parameters = 34,
4626         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4627         D3DPSREGISTER_SpecularPower = 36,
4628         D3DPSREGISTER_UserVec1 = 37,
4629         D3DPSREGISTER_UserVec2 = 38,
4630         D3DPSREGISTER_UserVec3 = 39,
4631         D3DPSREGISTER_UserVec4 = 40,
4632         D3DPSREGISTER_ViewTintColor = 41,
4633         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4634         D3DPSREGISTER_BloomColorSubtract = 43,
4635         D3DPSREGISTER_ViewToLight = 44, // float4x4
4636         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4637         // next at 52
4638 }
4639 D3DPSREGISTER_t;
4640
4641 /// information about each possible shader permutation
4642 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4643 /// currently selected permutation
4644 r_hlsl_permutation_t *r_hlsl_permutation;
4645 /// storage for permutations linked in the hash table
4646 memexpandablearray_t r_hlsl_permutationarray;
4647
4648 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4649 {
4650         //unsigned int hashdepth = 0;
4651         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4652         r_hlsl_permutation_t *p;
4653         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4654         {
4655                 if (p->mode == mode && p->permutation == permutation)
4656                 {
4657                         //if (hashdepth > 10)
4658                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4659                         return p;
4660                 }
4661                 //hashdepth++;
4662         }
4663         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4664         p->mode = mode;
4665         p->permutation = permutation;
4666         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4667         r_hlsl_permutationhash[mode][hashindex] = p;
4668         //if (hashdepth > 10)
4669         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4670         return p;
4671 }
4672
4673 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4674 {
4675         char *shaderstring;
4676         if (!filename || !filename[0])
4677                 return NULL;
4678         if (!strcmp(filename, "hlsl/default.hlsl"))
4679         {
4680                 if (!hlslshaderstring)
4681                 {
4682                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4683                         if (hlslshaderstring)
4684                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4685                         else
4686                                 hlslshaderstring = (char *)builtincgshaderstring;
4687                 }
4688                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4689                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4690                 return shaderstring;
4691         }
4692         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4693         if (shaderstring)
4694         {
4695                 if (printfromdisknotice)
4696                         Con_DPrintf("from disk %s... ", filename);
4697                 return shaderstring;
4698         }
4699         return shaderstring;
4700 }
4701
4702 #include <d3dx9.h>
4703 //#include <d3dx9shader.h>
4704 //#include <d3dx9mesh.h>
4705
4706 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4707 {
4708         DWORD *vsbin = NULL;
4709         DWORD *psbin = NULL;
4710         fs_offset_t vsbinsize;
4711         fs_offset_t psbinsize;
4712 //      IDirect3DVertexShader9 *vs = NULL;
4713 //      IDirect3DPixelShader9 *ps = NULL;
4714         ID3DXBuffer *vslog = NULL;
4715         ID3DXBuffer *vsbuffer = NULL;
4716         ID3DXConstantTable *vsconstanttable = NULL;
4717         ID3DXBuffer *pslog = NULL;
4718         ID3DXBuffer *psbuffer = NULL;
4719         ID3DXConstantTable *psconstanttable = NULL;
4720         int vsresult = 0;
4721         int psresult = 0;
4722         char temp[MAX_INPUTLINE];
4723         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4724         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4725         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4726         vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4727         psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4728         if ((!vsbin && vertstring) || (!psbin && fragstring))
4729         {
4730                 const char* dllnames_d3dx9 [] =
4731                 {
4732                         "d3dx9_43.dll",
4733                         "d3dx9_42.dll",
4734                         "d3dx9_41.dll",
4735                         "d3dx9_40.dll",
4736                         "d3dx9_39.dll",
4737                         "d3dx9_38.dll",
4738                         "d3dx9_37.dll",
4739                         "d3dx9_36.dll",
4740                         "d3dx9_35.dll",
4741                         "d3dx9_34.dll",
4742                         "d3dx9_33.dll",
4743                         "d3dx9_32.dll",
4744                         "d3dx9_31.dll",
4745                         "d3dx9_30.dll",
4746                         "d3dx9_29.dll",
4747                         "d3dx9_28.dll",
4748                         "d3dx9_27.dll",
4749                         "d3dx9_26.dll",
4750                         "d3dx9_25.dll",
4751                         "d3dx9_24.dll",
4752                         NULL
4753                 };
4754                 dllhandle_t d3dx9_dll = NULL;
4755                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4756 //              HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4757                 dllfunction_t d3dx9_dllfuncs[] =
4758                 {
4759                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4760 //                      {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4761                         {NULL, NULL}
4762                 };
4763                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4764                 {
4765                         DWORD shaderflags = 0;
4766 //                      shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4767                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4768                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4769                         if (vertstring && vertstring[0])
4770                         {
4771 //                              FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4772 //                              vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4773                                 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4774                                 if (vsbuffer)
4775                                 {
4776                                         vsbinsize = vsbuffer->GetBufferSize();
4777                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4778                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4779                                         vsbuffer->Release();
4780                                 }
4781                                 if (vslog)
4782                                 {
4783                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4784                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4785                                         vslog->Release();
4786                                 }
4787                         }
4788                         if (fragstring && fragstring[0])
4789                         {
4790 //                              FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4791 //                              psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4792                                 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4793                                 if (psbuffer)
4794                                 {
4795                                         psbinsize = psbuffer->GetBufferSize();
4796                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4797                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4798                                         psbuffer->Release();
4799                                 }
4800                                 if (pslog)
4801                                 {
4802                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4803                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4804                                         pslog->Release();
4805                                 }
4806                         }
4807                         Sys_UnloadLibrary(&d3dx9_dll);
4808                 }
4809                 else
4810                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4811         }
4812         if (vsbin)
4813         {
4814                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4815                 if (FAILED(vsresult))
4816                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4817         }
4818         if (psbin)
4819         {
4820                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4821                 if (FAILED(psresult))
4822                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4823         }
4824         // free the shader data
4825         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4826         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4827 }
4828
4829 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4830 {
4831         int i;
4832         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4833         int vertstrings_count = 0, vertstring_length = 0;
4834         int geomstrings_count = 0, geomstring_length = 0;
4835         int fragstrings_count = 0, fragstring_length = 0;
4836         char *t;
4837         char *vertexstring, *geometrystring, *fragmentstring;
4838         char *vertstring, *geomstring, *fragstring;
4839         const char *vertstrings_list[32+3];
4840         const char *geomstrings_list[32+3];
4841         const char *fragstrings_list[32+3];
4842         char permutationname[256];
4843         char cachename[256];
4844
4845         if (p->compiled)
4846                 return;
4847         p->compiled = true;
4848         p->vertexshader = NULL;
4849         p->pixelshader = NULL;
4850
4851         permutationname[0] = 0;
4852         cachename[0] = 0;
4853         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4854         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4855         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4856
4857         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4858         strlcat(cachename, "hlsl/", sizeof(cachename));
4859
4860         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4861         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4862         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4863         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4864
4865         // the first pretext is which type of shader to compile as
4866         // (later these will all be bound together as a program object)
4867         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4868         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4869         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4870
4871         // the second pretext is the mode (for example a light source)
4872         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4873         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4874         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4875         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4876         strlcat(cachename, modeinfo->name, sizeof(cachename));
4877
4878         // now add all the permutation pretexts
4879         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4880         {
4881                 if (permutation & (1<<i))
4882                 {
4883                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4884                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4885                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4886                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4887                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4888                 }
4889                 else
4890                 {
4891                         // keep line numbers correct
4892                         vertstrings_list[vertstrings_count++] = "\n";
4893                         geomstrings_list[geomstrings_count++] = "\n";
4894                         fragstrings_list[fragstrings_count++] = "\n";
4895                 }
4896         }
4897
4898         // replace spaces in the cachename with _ characters
4899         for (i = 0;cachename[i];i++)
4900                 if (cachename[i] == ' ')
4901                         cachename[i] = '_';
4902
4903         // now append the shader text itself
4904         vertstrings_list[vertstrings_count++] = vertexstring;
4905         geomstrings_list[geomstrings_count++] = geometrystring;
4906         fragstrings_list[fragstrings_count++] = fragmentstring;
4907
4908         // if any sources were NULL, clear the respective list
4909         if (!vertexstring)
4910                 vertstrings_count = 0;
4911         if (!geometrystring)
4912                 geomstrings_count = 0;
4913         if (!fragmentstring)
4914                 fragstrings_count = 0;
4915
4916         vertstring_length = 0;
4917         for (i = 0;i < vertstrings_count;i++)
4918                 vertstring_length += strlen(vertstrings_list[i]);
4919         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4920         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4921                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4922
4923         geomstring_length = 0;
4924         for (i = 0;i < geomstrings_count;i++)
4925                 geomstring_length += strlen(geomstrings_list[i]);
4926         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4927         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4928                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4929
4930         fragstring_length = 0;
4931         for (i = 0;i < fragstrings_count;i++)
4932                 fragstring_length += strlen(fragstrings_list[i]);
4933         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4934         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4935                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4936
4937         // try to load the cached shader, or generate one
4938         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4939
4940         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4941                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4942         else
4943                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4944
4945         // free the strings
4946         if (vertstring)
4947                 Mem_Free(vertstring);
4948         if (geomstring)
4949                 Mem_Free(geomstring);
4950         if (fragstring)
4951                 Mem_Free(fragstring);
4952         if (vertexstring)
4953                 Mem_Free(vertexstring);
4954         if (geometrystring)
4955                 Mem_Free(geometrystring);
4956         if (fragmentstring)
4957                 Mem_Free(fragmentstring);
4958 }
4959
4960 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4961 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4962 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4963 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4964 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4965 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4966
4967 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4968 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4969 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4970 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4971 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4972 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4973
4974 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4975 {
4976         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4977         if (r_hlsl_permutation != perm)
4978         {
4979                 r_hlsl_permutation = perm;
4980                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4981                 {
4982                         if (!r_hlsl_permutation->compiled)
4983                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4984                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4985                         {
4986                                 // remove features until we find a valid permutation
4987                                 int i;
4988                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4989                                 {
4990                                         // reduce i more quickly whenever it would not remove any bits
4991                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4992                                         if (!(permutation & j))
4993                                                 continue;
4994                                         permutation -= j;
4995                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4996                                         if (!r_hlsl_permutation->compiled)
4997                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4998                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4999                                                 break;
5000                                 }
5001                                 if (i >= SHADERPERMUTATION_COUNT)
5002                                 {
5003                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
5004                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
5005                                         return; // no bit left to clear, entire mode is broken
5006                                 }
5007                         }
5008                 }
5009                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
5010                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
5011         }
5012         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5013         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5014         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
5015 }
5016 #endif
5017
5018 void R_GLSL_Restart_f(void)
5019 {
5020         unsigned int i, limit;
5021         if (glslshaderstring && glslshaderstring != builtinshaderstring)
5022                 Mem_Free(glslshaderstring);
5023         glslshaderstring = NULL;
5024         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
5025                 Mem_Free(cgshaderstring);
5026         cgshaderstring = NULL;
5027         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
5028                 Mem_Free(hlslshaderstring);
5029         hlslshaderstring = NULL;
5030         switch(vid.renderpath)
5031         {
5032         case RENDERPATH_D3D9:
5033 #ifdef SUPPORTD3D
5034                 {
5035                         r_hlsl_permutation_t *p;
5036                         r_hlsl_permutation = NULL;
5037 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5038 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5039 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5040 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5041                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
5042                         for (i = 0;i < limit;i++)
5043                         {
5044                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
5045                                 {
5046                                         if (p->vertexshader)
5047                                                 IDirect3DVertexShader9_Release(p->vertexshader);
5048                                         if (p->pixelshader)
5049                                                 IDirect3DPixelShader9_Release(p->pixelshader);
5050                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
5051                                 }
5052                         }
5053                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
5054                 }
5055 #endif
5056                 break;
5057         case RENDERPATH_D3D10:
5058                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5059                 break;
5060         case RENDERPATH_D3D11:
5061                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5062                 break;
5063         case RENDERPATH_GL20:
5064                 {
5065                         r_glsl_permutation_t *p;
5066                         r_glsl_permutation = NULL;
5067                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
5068                         for (i = 0;i < limit;i++)
5069                         {
5070                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
5071                                 {
5072                                         GL_Backend_FreeProgram(p->program);
5073                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5074                                 }
5075                         }
5076                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5077                 }
5078                 break;
5079         case RENDERPATH_CGGL:
5080 #ifdef SUPPORTCG
5081                 {
5082                         r_cg_permutation_t *p;
5083                         r_cg_permutation = NULL;
5084                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5085                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5086                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5087                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5088                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5089                         for (i = 0;i < limit;i++)
5090                         {
5091                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5092                                 {
5093                                         if (p->vprogram)
5094                                                 cgDestroyProgram(p->vprogram);
5095                                         if (p->fprogram)
5096                                                 cgDestroyProgram(p->fprogram);
5097                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5098                                 }
5099                         }
5100                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5101                 }
5102 #endif
5103                 break;
5104         case RENDERPATH_GL13:
5105         case RENDERPATH_GL11:
5106                 break;
5107         }
5108 }
5109
5110 void R_GLSL_DumpShader_f(void)
5111 {
5112         int i;
5113         qfile_t *file;
5114
5115         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5116         if (file)
5117         {
5118                 FS_Print(file, "/* The engine may define the following macros:\n");
5119                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5120                 for (i = 0;i < SHADERMODE_COUNT;i++)
5121                         FS_Print(file, glslshadermodeinfo[i].pretext);
5122                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5123                         FS_Print(file, shaderpermutationinfo[i].pretext);
5124                 FS_Print(file, "*/\n");
5125                 FS_Print(file, builtinshaderstring);
5126                 FS_Close(file);
5127                 Con_Printf("glsl/default.glsl written\n");
5128         }
5129         else
5130                 Con_Printf("failed to write to glsl/default.glsl\n");
5131
5132 #ifdef SUPPORTCG
5133         file = FS_OpenRealFile("cg/default.cg", "w", false);
5134         if (file)
5135         {
5136                 FS_Print(file, "/* The engine may define the following macros:\n");
5137                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5138                 for (i = 0;i < SHADERMODE_COUNT;i++)
5139                         FS_Print(file, cgshadermodeinfo[i].pretext);
5140                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5141                         FS_Print(file, shaderpermutationinfo[i].pretext);
5142                 FS_Print(file, "*/\n");
5143                 FS_Print(file, builtincgshaderstring);
5144                 FS_Close(file);
5145                 Con_Printf("cg/default.cg written\n");
5146         }
5147         else
5148                 Con_Printf("failed to write to cg/default.cg\n");
5149 #endif
5150
5151 #ifdef SUPPORTD3D
5152         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5153         if (file)
5154         {
5155                 FS_Print(file, "/* The engine may define the following macros:\n");
5156                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5157                 for (i = 0;i < SHADERMODE_COUNT;i++)
5158                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5159                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5160                         FS_Print(file, shaderpermutationinfo[i].pretext);
5161                 FS_Print(file, "*/\n");
5162                 FS_Print(file, builtincgshaderstring);
5163                 FS_Close(file);
5164                 Con_Printf("hlsl/default.hlsl written\n");
5165         }
5166         else
5167                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5168 #endif
5169 }
5170
5171 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5172 {
5173         if (!second)
5174                 texturemode = GL_MODULATE;
5175         switch (vid.renderpath)
5176         {
5177         case RENDERPATH_D3D9:
5178 #ifdef SUPPORTD3D
5179                 R_SetupShader_SetPermutationHLSL(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))));
5180                 R_Mesh_TexBind(GL20TU_FIRST , first );
5181                 R_Mesh_TexBind(GL20TU_SECOND, second);
5182 #endif
5183                 break;
5184         case RENDERPATH_D3D10:
5185                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5186                 break;
5187         case RENDERPATH_D3D11:
5188                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5189                 break;
5190         case RENDERPATH_GL20:
5191                 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))));
5192                 R_Mesh_TexBind(GL20TU_FIRST , first );
5193                 R_Mesh_TexBind(GL20TU_SECOND, second);
5194                 break;
5195         case RENDERPATH_CGGL:
5196 #ifdef SUPPORTCG
5197                 CHECKCGERROR
5198                 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))));
5199                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5200                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5201 #endif
5202                 break;
5203         case RENDERPATH_GL13:
5204                 R_Mesh_TexBind(0, first );
5205                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5206                 R_Mesh_TexBind(1, second);
5207                 if (second)
5208                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5209                 break;
5210         case RENDERPATH_GL11:
5211                 R_Mesh_TexBind(0, first );
5212                 break;
5213         }
5214 }
5215
5216 void R_SetupShader_DepthOrShadow(void)
5217 {
5218         switch (vid.renderpath)
5219         {
5220         case RENDERPATH_D3D9:
5221 #ifdef SUPPORTD3D
5222                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5223 #endif
5224                 break;
5225         case RENDERPATH_D3D10:
5226                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5227                 break;
5228         case RENDERPATH_D3D11:
5229                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5230                 break;
5231         case RENDERPATH_GL20:
5232                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5233                 break;
5234         case RENDERPATH_CGGL:
5235 #ifdef SUPPORTCG
5236                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5237 #endif
5238                 break;
5239         case RENDERPATH_GL13:
5240                 R_Mesh_TexBind(0, 0);
5241                 R_Mesh_TexBind(1, 0);
5242                 break;
5243         case RENDERPATH_GL11:
5244                 R_Mesh_TexBind(0, 0);
5245                 break;
5246         }
5247 }
5248
5249 void R_SetupShader_ShowDepth(void)
5250 {
5251         switch (vid.renderpath)
5252         {
5253         case RENDERPATH_D3D9:
5254 #ifdef SUPPORTHLSL
5255                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5256 #endif
5257                 break;
5258         case RENDERPATH_D3D10:
5259                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5260                 break;
5261         case RENDERPATH_D3D11:
5262                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5263                 break;
5264         case RENDERPATH_GL20:
5265                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5266                 break;
5267         case RENDERPATH_CGGL:
5268 #ifdef SUPPORTCG
5269                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5270 #endif
5271                 break;
5272         case RENDERPATH_GL13:
5273                 break;
5274         case RENDERPATH_GL11:
5275                 break;
5276         }
5277 }
5278
5279 extern qboolean r_shadow_usingdeferredprepass;
5280 extern cvar_t r_shadow_deferred_8bitrange;
5281 extern rtexture_t *r_shadow_attenuationgradienttexture;
5282 extern rtexture_t *r_shadow_attenuation2dtexture;
5283 extern rtexture_t *r_shadow_attenuation3dtexture;
5284 extern qboolean r_shadow_usingshadowmaprect;
5285 extern qboolean r_shadow_usingshadowmapcube;
5286 extern qboolean r_shadow_usingshadowmap2d;
5287 extern qboolean r_shadow_usingshadowmaportho;
5288 extern float r_shadow_shadowmap_texturescale[2];
5289 extern float r_shadow_shadowmap_parameters[4];
5290 extern qboolean r_shadow_shadowmapvsdct;
5291 extern qboolean r_shadow_shadowmapsampler;
5292 extern int r_shadow_shadowmappcf;
5293 extern rtexture_t *r_shadow_shadowmaprectangletexture;
5294 extern rtexture_t *r_shadow_shadowmap2dtexture;
5295 extern rtexture_t *r_shadow_shadowmapcubetexture[R_SHADOW_SHADOWMAP_NUMCUBEMAPS];
5296 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5297 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5298 extern matrix4x4_t r_shadow_shadowmapmatrix;
5299 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5300 extern int r_shadow_prepass_width;
5301 extern int r_shadow_prepass_height;
5302 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5303 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5304 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5305 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5306 extern cvar_t gl_mesh_separatearrays;
5307 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5308 {
5309         // a blendfunc allows colormod if:
5310         // a) it can never keep the destination pixel invariant, or
5311         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5312         // this is to prevent unintended side effects from colormod
5313
5314         // in formulas:
5315         // IF there is a (s, sa) for which for all (d, da),
5316         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5317         // THEN, for this (s, sa) and all (colormod, d, da):
5318         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5319         // OBVIOUSLY, this means that
5320         //   s*colormod * src(s*colormod, d, sa, da) = 0
5321         //   dst(s*colormod, d, sa, da)              = 1
5322
5323         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5324
5325         // main condition to leave dst color invariant:
5326         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5327         //   src == GL_ZERO:
5328         //     s * 0 + d * dst(s, d, sa, da) == d
5329         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5330         //       => colormod is a problem for GL_SRC_COLOR only
5331         //   src == GL_ONE:
5332         //     s + d * dst(s, d, sa, da) == d
5333         //       => s == 0
5334         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5335         //       => colormod is never problematic for these
5336         //   src == GL_SRC_COLOR:
5337         //     s*s + d * dst(s, d, sa, da) == d
5338         //       => s == 0
5339         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5340         //       => colormod is never problematic for these
5341         //   src == GL_ONE_MINUS_SRC_COLOR:
5342         //     s*(1-s) + d * dst(s, d, sa, da) == d
5343         //       => s == 0 or s == 1
5344         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5345         //       => colormod is a problem for GL_SRC_COLOR only
5346         //   src == GL_DST_COLOR
5347         //     s*d + d * dst(s, d, sa, da) == d
5348         //       => s == 1
5349         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5350         //       => colormod is always a problem
5351         //     or
5352         //       => s == 0
5353         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5354         //       => colormod is never problematic for these
5355         //       => BUT, we do not know s! We must assume it is problematic
5356         //       then... except in GL_ONE case, where we know all invariant
5357         //       cases are fine
5358         //   src == GL_ONE_MINUS_DST_COLOR
5359         //     s*(1-d) + d * dst(s, d, sa, da) == d
5360         //       => s == 0 (1-d is impossible to handle for our desired result)
5361         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5362         //       => colormod is never problematic for these
5363         //   src == GL_SRC_ALPHA
5364         //     s*sa + d * dst(s, d, sa, da) == d
5365         //       => s == 0, or sa == 0
5366         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5367         //       => colormod breaks in the case GL_SRC_COLOR only
5368         //   src == GL_ONE_MINUS_SRC_ALPHA
5369         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5370         //       => s == 0, or sa == 1
5371         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5372         //       => colormod breaks in the case GL_SRC_COLOR only
5373         //   src == GL_DST_ALPHA
5374         //     s*da + d * dst(s, d, sa, da) == d
5375         //       => s == 0
5376         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5377         //       => colormod is never problematic for these
5378
5379         switch(src)
5380         {
5381                 case GL_ZERO:
5382                 case GL_ONE_MINUS_SRC_COLOR:
5383                 case GL_SRC_ALPHA:
5384                 case GL_ONE_MINUS_SRC_ALPHA:
5385                         if(dst == GL_SRC_COLOR)
5386                                 return false;
5387                         return true;
5388                 case GL_ONE:
5389                 case GL_SRC_COLOR:
5390                 case GL_ONE_MINUS_DST_COLOR:
5391                 case GL_DST_ALPHA:
5392                 case GL_ONE_MINUS_DST_ALPHA:
5393                         return true;
5394                 case GL_DST_COLOR:
5395                         if(dst == GL_ONE)
5396                                 return true;
5397                         return false;
5398                 default:
5399                         return false;
5400         }
5401 }
5402 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, void *surfacewaterplane)
5403 {
5404         // select a permutation of the lighting shader appropriate to this
5405         // combination of texture, entity, light source, and fogging, only use the
5406         // minimum features necessary to avoid wasting rendering time in the
5407         // fragment shader on features that are not being used
5408         unsigned int permutation = 0;
5409         unsigned int mode = 0;
5410         qboolean allow_colormod;
5411         static float dummy_colormod[3] = {1, 1, 1};
5412         float *colormod = rsurface.colormod;
5413         float m16f[16];
5414         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5415         if (rsurfacepass == RSURFPASS_BACKGROUND)
5416         {
5417                 // distorted background
5418                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5419                         mode = SHADERMODE_WATER;
5420                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5421                         mode = SHADERMODE_REFRACTION;
5422                 else
5423                 {
5424                         mode = SHADERMODE_GENERIC;
5425                         permutation |= SHADERPERMUTATION_DIFFUSE;
5426                 }
5427                 GL_AlphaTest(false);
5428                 GL_BlendFunc(GL_ONE, GL_ZERO);
5429                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5430         }
5431         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5432         {
5433                 if (r_glsl_offsetmapping.integer)
5434                 {
5435                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5436                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5437                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5438                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5439                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5440                         {
5441                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5442                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5443                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5444                         }
5445                 }
5446                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5447                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5449                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5450                 // normalmap (deferred prepass), may use alpha test on diffuse
5451                 mode = SHADERMODE_DEFERREDGEOMETRY;
5452                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5453                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5454                 GL_AlphaTest(false);
5455                 GL_BlendFunc(GL_ONE, GL_ZERO);
5456                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5457         }
5458         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5459         {
5460                 if (r_glsl_offsetmapping.integer)
5461                 {
5462                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5463                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5464                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5465                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5466                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5467                         {
5468                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5469                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5470                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5471                         }
5472                 }
5473                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5474                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5475                 // light source
5476                 mode = SHADERMODE_LIGHTSOURCE;
5477                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5478                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5479                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5480                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5481                 if (diffusescale > 0)
5482                         permutation |= SHADERPERMUTATION_DIFFUSE;
5483                 if (specularscale > 0)
5484                 {
5485                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5486                         if (r_shadow_glossexact.integer)
5487                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5488                 }
5489                 if (r_refdef.fogenabled)
5490                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5491                 if (rsurface.texture->colormapping)
5492                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5493                 if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
5494                 {
5495                         if (r_shadow_usingshadowmaprect)
5496                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5497                         if (r_shadow_usingshadowmap2d)
5498                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5499                         if (r_shadow_usingshadowmapcube)
5500                                 permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
5501                         else if(r_shadow_shadowmapvsdct)
5502                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5503
5504                         if (r_shadow_shadowmapsampler)
5505                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5506                         if (r_shadow_shadowmappcf > 1)
5507                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5508                         else if (r_shadow_shadowmappcf)
5509                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5510                 }
5511                 if (rsurface.texture->reflectmasktexture)
5512                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5513                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5514                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5515                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5516         }
5517         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5518         {
5519                 if (r_glsl_offsetmapping.integer)
5520                 {
5521                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5522                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5523                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5524                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5525                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5526                         {
5527                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5528                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5529                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5530                         }
5531                 }
5532                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5533                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5534                 // unshaded geometry (fullbright or ambient model lighting)
5535                 mode = SHADERMODE_FLATCOLOR;
5536                 ambientscale = diffusescale = specularscale = 0;
5537                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5538                         permutation |= SHADERPERMUTATION_GLOW;
5539                 if (r_refdef.fogenabled)
5540                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5541                 if (rsurface.texture->colormapping)
5542                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5543                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5544                 {
5545                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5546                         if (r_shadow_usingshadowmaprect)
5547                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5548                         if (r_shadow_usingshadowmap2d)
5549                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5550
5551                         if (r_shadow_shadowmapsampler)
5552                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5553                         if (r_shadow_shadowmappcf > 1)
5554                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5555                         else if (r_shadow_shadowmappcf)
5556                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5557                 }
5558                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5559                         permutation |= SHADERPERMUTATION_REFLECTION;
5560                 if (rsurface.texture->reflectmasktexture)
5561                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5562                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5563                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5564                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5565         }
5566         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5567         {
5568                 if (r_glsl_offsetmapping.integer)
5569                 {
5570                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5571                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5572                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5573                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5574                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5575                         {
5576                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5577                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5578                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5579                         }
5580                 }
5581                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5582                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5583                 // directional model lighting
5584                 mode = SHADERMODE_LIGHTDIRECTION;
5585                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5586                         permutation |= SHADERPERMUTATION_GLOW;
5587                 permutation |= SHADERPERMUTATION_DIFFUSE;
5588                 if (specularscale > 0)
5589                 {
5590                         permutation |= SHADERPERMUTATION_SPECULAR;
5591                         if (r_shadow_glossexact.integer)
5592                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5593                 }
5594                 if (r_refdef.fogenabled)
5595                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5596                 if (rsurface.texture->colormapping)
5597                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5598                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5599                 {
5600                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5601                         if (r_shadow_usingshadowmaprect)
5602                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5603                         if (r_shadow_usingshadowmap2d)
5604                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5605
5606                         if (r_shadow_shadowmapsampler)
5607                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5608                         if (r_shadow_shadowmappcf > 1)
5609                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5610                         else if (r_shadow_shadowmappcf)
5611                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5612                 }
5613                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5614                         permutation |= SHADERPERMUTATION_REFLECTION;
5615                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5616                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5617                 if (rsurface.texture->reflectmasktexture)
5618                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5619                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5620                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5621                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5622         }
5623         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5624         {
5625                 if (r_glsl_offsetmapping.integer)
5626                 {
5627                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5628                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5629                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5630                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5631                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5632                         {
5633                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5634                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5635                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5636                         }
5637                 }
5638                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5639                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5640                 // ambient model lighting
5641                 mode = SHADERMODE_LIGHTDIRECTION;
5642                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5643                         permutation |= SHADERPERMUTATION_GLOW;
5644                 if (r_refdef.fogenabled)
5645                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5646                 if (rsurface.texture->colormapping)
5647                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5648                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5649                 {
5650                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5651                         if (r_shadow_usingshadowmaprect)
5652                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5653                         if (r_shadow_usingshadowmap2d)
5654                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5655
5656                         if (r_shadow_shadowmapsampler)
5657                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5658                         if (r_shadow_shadowmappcf > 1)
5659                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5660                         else if (r_shadow_shadowmappcf)
5661                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5662                 }
5663                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5664                         permutation |= SHADERPERMUTATION_REFLECTION;
5665                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5666                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5667                 if (rsurface.texture->reflectmasktexture)
5668                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5669                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5670                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5671                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5672         }
5673         else
5674         {
5675                 if (r_glsl_offsetmapping.integer)
5676                 {
5677                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5678                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5679                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5680                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5681                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5682                         {
5683                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5684                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5685                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5686                         }
5687                 }
5688                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5689                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5690                 // lightmapped wall
5691                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5692                         permutation |= SHADERPERMUTATION_GLOW;
5693                 if (r_refdef.fogenabled)
5694                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5695                 if (rsurface.texture->colormapping)
5696                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5697                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5698                 {
5699                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5700                         if (r_shadow_usingshadowmaprect)
5701                                 permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
5702                         if (r_shadow_usingshadowmap2d)
5703                                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5704
5705                         if (r_shadow_shadowmapsampler)
5706                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5707                         if (r_shadow_shadowmappcf > 1)
5708                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5709                         else if (r_shadow_shadowmappcf)
5710                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5711                 }
5712                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5713                         permutation |= SHADERPERMUTATION_REFLECTION;
5714                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5715                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5716                 if (rsurface.texture->reflectmasktexture)
5717                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5718                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5719                 {
5720                         // deluxemapping (light direction texture)
5721                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5722                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5723                         else
5724                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5725                         permutation |= SHADERPERMUTATION_DIFFUSE;
5726                         if (specularscale > 0)
5727                         {
5728                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5729                                 if (r_shadow_glossexact.integer)
5730                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5731                         }
5732                 }
5733                 else if (r_glsl_deluxemapping.integer >= 2)
5734                 {
5735                         // fake deluxemapping (uniform light direction in tangentspace)
5736                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5737                         permutation |= SHADERPERMUTATION_DIFFUSE;
5738                         if (specularscale > 0)
5739                         {
5740                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5741                                 if (r_shadow_glossexact.integer)
5742                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5743                         }
5744                 }
5745                 else if (rsurface.uselightmaptexture)
5746                 {
5747                         // ordinary lightmapping (q1bsp, q3bsp)
5748                         mode = SHADERMODE_LIGHTMAP;
5749                 }
5750                 else
5751                 {
5752                         // ordinary vertex coloring (q3bsp)
5753                         mode = SHADERMODE_VERTEXCOLOR;
5754                 }
5755                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5756                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5757                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5758         }
5759         if(!allow_colormod)
5760                 colormod = dummy_colormod;
5761         switch(vid.renderpath)
5762         {
5763         case RENDERPATH_D3D9:
5764 #ifdef SUPPORTD3D
5765                 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);
5766                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5767                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5768                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5769                 if (mode == SHADERMODE_LIGHTSOURCE)
5770                 {
5771                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5772                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5773                 }
5774                 else
5775                 {
5776                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5777                         {
5778                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5779                         }
5780                 }
5781                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5782                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5783                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5784                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5785                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5786
5787                 if (mode == SHADERMODE_LIGHTSOURCE)
5788                 {
5789                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5790                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5791                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5792                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5793                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5794
5795                         // additive passes are only darkened by fog, not tinted
5796                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5797                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5798                 }
5799                 else
5800                 {
5801                         if (mode == SHADERMODE_FLATCOLOR)
5802                         {
5803                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5804                         }
5805                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5806                         {
5807                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5808                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5809                                 hlslPSSetParameter3f(D3DPSREGISTER_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);
5810                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5811                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5812                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5813                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5814                         }
5815                         else
5816                         {
5817                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5818                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5819                                 hlslPSSetParameter3f(D3DPSREGISTER_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);
5820                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5821                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5822                         }
5823                         // additive passes are only darkened by fog, not tinted
5824                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5825                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5826                         else
5827                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5828                         hlslPSSetParameter4f(D3DPSREGISTER_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);
5829                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5830                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5831                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5832                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5833                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5834                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5835                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5836                 }
5837                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5838                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5839                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5840                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5841                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5842                 if (rsurface.texture->pantstexture)
5843                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5844                 else
5845                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5846                 if (rsurface.texture->shirttexture)
5847                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5848                 else
5849                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5850                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5851                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5852                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5853                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5854                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5855                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5856                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5857
5858                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5859                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5860                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5861                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5862                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5863                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5864                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5865                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5866                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5867                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5868                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5869                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5870                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5871                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5872                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5873                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5874                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5875                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5876                 {
5877                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5878                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5879                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5880                 }
5881                 else
5882                 {
5883                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5884                 }
5885 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5886 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5887                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5888                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5889                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5890                 {
5891                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5892                         if (rsurface.rtlight)
5893                         {
5894                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5895                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5896                         }
5897                 }
5898 #endif
5899                 break;
5900         case RENDERPATH_D3D10:
5901                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5902                 break;
5903         case RENDERPATH_D3D11:
5904                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5905                 break;
5906         case RENDERPATH_GL20:
5907                 if (gl_mesh_separatearrays.integer)
5908                 {
5909                         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);
5910                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5911                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5912                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5913                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5914                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5915                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5916                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5917                 }
5918                 else
5919                 {
5920                         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);
5921                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5922                 }
5923                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5924                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5925                 if (mode == SHADERMODE_LIGHTSOURCE)
5926                 {
5927                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5928                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5929                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5930                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5931                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5932                         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);
5933         
5934                         // additive passes are only darkened by fog, not tinted
5935                         if (r_glsl_permutation->loc_FogColor >= 0)
5936                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5937                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5938                 }
5939                 else
5940                 {
5941                         if (mode == SHADERMODE_FLATCOLOR)
5942                         {
5943                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5944                         }
5945                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5946                         {
5947                                 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
5948                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5949                                 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);
5950                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5951                                 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);
5952                                 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]);
5953                                 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]);
5954                         }
5955                         else
5956                         {
5957                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5958                                 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]);
5959                                 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);
5960                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5961                                 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);
5962                         }
5963                         // additive passes are only darkened by fog, not tinted
5964                         if (r_glsl_permutation->loc_FogColor >= 0)
5965                         {
5966                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5967                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5968                                 else
5969                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5970                         }
5971                         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);
5972                         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]);
5973                         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]);
5974                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5975                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5976                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5977                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5978                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5979                 }
5980                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5981                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5982                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5983                 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]);
5984                 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]);
5985
5986                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5987                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5988                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5989                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5990                 {
5991                         if (rsurface.texture->pantstexture)
5992                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5993                         else
5994                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5995                 }
5996                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5997                 {
5998                         if (rsurface.texture->shirttexture)
5999                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6000                         else
6001                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
6002                 }
6003                 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]);
6004                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
6005                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
6006                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
6007                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6008                 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]);
6009                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6010
6011         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6012         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6013         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6014                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6015                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6016                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6017                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6018                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6019                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6020                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6021                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6022                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6023                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6024                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6025                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6026                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6027                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6028                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6029                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6030                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6031                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6032                 {
6033                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6034                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6035                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6036                 }
6037                 else
6038                 {
6039                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6040                 }
6041 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6042 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6043                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6044                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6045                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6046                 {
6047                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6048                         if (r_glsl_permutation->loc_Texture_ShadowMapRect   >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHORECT : GL20TU_SHADOWMAPRECT, r_shadow_shadowmaprectangletexture                  );
6049                         if (rsurface.rtlight)
6050                         {
6051                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6052                                 if (r_shadow_usingshadowmapcube)
6053                                         if (r_glsl_permutation->loc_Texture_ShadowMapCube   >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE     , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6054                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6055                         }
6056                 }
6057                 CHECKGLERROR
6058                 break;
6059         case RENDERPATH_CGGL:
6060 #ifdef SUPPORTCG
6061                 if (gl_mesh_separatearrays.integer)
6062                 {
6063                         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);
6064                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
6065                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
6066                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
6067                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
6068                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6069                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6070                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6071                 }
6072                 else
6073                 {
6074                         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);
6075                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6076                 }
6077                 R_SetupShader_SetPermutationCG(mode, permutation);
6078                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6079                 if (mode == SHADERMODE_LIGHTSOURCE)
6080                 {
6081                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6082                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6083                 }
6084                 else
6085                 {
6086                         if (mode == SHADERMODE_LIGHTDIRECTION)
6087                         {
6088                                 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
6089                         }
6090                 }
6091                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6092                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6093                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6094                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6095                 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
6096                 CHECKGLERROR
6097
6098                 if (mode == SHADERMODE_LIGHTSOURCE)
6099                 {
6100                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6101                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6102                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6103                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6104                         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
6105
6106                         // additive passes are only darkened by fog, not tinted
6107                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6108                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6109                 }
6110                 else
6111                 {
6112                         if (mode == SHADERMODE_FLATCOLOR)
6113                         {
6114                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6115                         }
6116                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6117                         {
6118                                 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) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);CHECKCGERROR
6119                                 if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);CHECKCGERROR
6120                                 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
6121                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6122                                 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
6123                                 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
6124                                 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
6125                         }
6126                         else
6127                         {
6128                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);CHECKCGERROR
6129                                 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
6130                                 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
6131                                 if (r_cg_permutation->fp_DeferredMod_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);CHECKCGERROR
6132                                 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
6133                         }
6134                         // additive passes are only darkened by fog, not tinted
6135                         if (r_cg_permutation->fp_FogColor)
6136                         {
6137                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6138                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6139                                 else
6140                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6141                                 CHECKCGERROR
6142                         }
6143                         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
6144                         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
6145                         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
6146                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
6147                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
6148                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6149                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6150                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
6151                 }
6152                 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
6153                 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
6154                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6155                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
6156                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6157                 if (r_cg_permutation->fp_Color_Pants)
6158                 {
6159                         if (rsurface.texture->pantstexture)
6160                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6161                         else
6162                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6163                         CHECKCGERROR
6164                 }
6165                 if (r_cg_permutation->fp_Color_Shirt)
6166                 {
6167                         if (rsurface.texture->shirttexture)
6168                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6169                         else
6170                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6171                         CHECKCGERROR
6172                 }
6173                 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
6174                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6175                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6176                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6177                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6178                 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
6179                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6180
6181         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6182         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6183         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6184                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6185                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6186                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6187                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6188                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6189                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6190                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6191                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6192                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6193                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6194                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6195                 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
6196                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6197                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6198                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6199                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6200                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6201                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6202                 {
6203                         if (r_cg_permutation->fp_Texture_Refraction     ) CG_BindTexture(r_cg_permutation->fp_Texture_Refraction     , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);CHECKCGERROR
6204                         else if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);CHECKCGERROR
6205                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6206                 }
6207                 else
6208                 {
6209                         if (r_cg_permutation->fp_Texture_Reflection     ) CG_BindTexture(r_cg_permutation->fp_Texture_Reflection     , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);CHECKCGERROR
6210                 }
6211                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6212                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6213                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6214                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6215                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6216                 {
6217                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6218                         if (r_cg_permutation->fp_Texture_ShadowMapRect  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6219                         if (rsurface.rtlight)
6220                         {
6221                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6222                                 if (r_shadow_usingshadowmapcube)
6223                                         if (r_cg_permutation->fp_Texture_ShadowMapCube  ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6224                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6225                         }
6226                 }
6227
6228                 CHECKGLERROR
6229 #endif
6230                 break;
6231         case RENDERPATH_GL13:
6232         case RENDERPATH_GL11:
6233                 break;
6234         }
6235 }
6236
6237 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6238 {
6239         // select a permutation of the lighting shader appropriate to this
6240         // combination of texture, entity, light source, and fogging, only use the
6241         // minimum features necessary to avoid wasting rendering time in the
6242         // fragment shader on features that are not being used
6243         unsigned int permutation = 0;
6244         unsigned int mode = 0;
6245         const float *lightcolorbase = rtlight->currentcolor;
6246         float ambientscale = rtlight->ambientscale;
6247         float diffusescale = rtlight->diffusescale;
6248         float specularscale = rtlight->specularscale;
6249         // this is the location of the light in view space
6250         vec3_t viewlightorigin;
6251         // this transforms from view space (camera) to light space (cubemap)
6252         matrix4x4_t viewtolight;
6253         matrix4x4_t lighttoview;
6254         float viewtolight16f[16];
6255         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6256         // light source
6257         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6258         if (rtlight->currentcubemap != r_texture_whitecube)
6259                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6260         if (diffusescale > 0)
6261                 permutation |= SHADERPERMUTATION_DIFFUSE;
6262         if (specularscale > 0)
6263         {
6264                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6265                 if (r_shadow_glossexact.integer)
6266                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6267         }
6268         if (r_shadow_usingshadowmaprect || r_shadow_usingshadowmap2d || r_shadow_usingshadowmapcube)
6269         {
6270                 if (r_shadow_usingshadowmaprect)
6271                         permutation |= SHADERPERMUTATION_SHADOWMAPRECT;
6272                 if (r_shadow_usingshadowmap2d)
6273                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6274                 if (r_shadow_usingshadowmapcube)
6275                         permutation |= SHADERPERMUTATION_SHADOWMAPCUBE;
6276                 else if(r_shadow_shadowmapvsdct)
6277                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6278
6279                 if (r_shadow_shadowmapsampler)
6280                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6281                 if (r_shadow_shadowmappcf > 1)
6282                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6283                 else if (r_shadow_shadowmappcf)
6284                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6285         }
6286         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6287         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6288         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6289         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6290         switch(vid.renderpath)
6291         {
6292         case RENDERPATH_D3D9:
6293 #ifdef SUPPORTD3D
6294                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6295                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6296                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6297                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6298                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6299                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6300                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6301                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6302                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6303                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6304                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6305
6306                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6307                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6308                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6309                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6310                 R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6311                 if (r_shadow_usingshadowmapcube)
6312                         R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6313                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6314                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6315 #endif
6316                 break;
6317         case RENDERPATH_D3D10:
6318                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6319                 break;
6320         case RENDERPATH_D3D11:
6321                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6322                 break;
6323         case RENDERPATH_GL20:
6324                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6325                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6326                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6327                 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);
6328                 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);
6329                 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);
6330                 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]);
6331                 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]);
6332                 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));
6333                 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]);
6334                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6335
6336                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6337                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6338                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6339                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6340                 if (r_glsl_permutation->loc_Texture_ShadowMapRect     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPRECT      , r_shadow_shadowmaprectangletexture                  );
6341                 if (r_shadow_usingshadowmapcube)
6342                         if (r_glsl_permutation->loc_Texture_ShadowMapCube     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAPCUBE      , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);
6343                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6344                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6345                 break;
6346         case RENDERPATH_CGGL:
6347 #ifdef SUPPORTCG
6348                 R_SetupShader_SetPermutationCG(mode, permutation);
6349                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6350                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6351                 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
6352                 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
6353                 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
6354                 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
6355                 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
6356                 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
6357                 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
6358                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6359
6360                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6361                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6362                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6363                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6364                 if (r_cg_permutation->fp_Texture_ShadowMapRect    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapRect  , r_shadow_shadowmaprectangletexture                  );CHECKCGERROR
6365                 if (r_shadow_usingshadowmapcube)
6366                         if (r_cg_permutation->fp_Texture_ShadowMapCube    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMapCube  , r_shadow_shadowmapcubetexture[r_shadow_shadowmaplod]);CHECKCGERROR
6367                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6368                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6369 #endif
6370                 break;
6371         case RENDERPATH_GL13:
6372         case RENDERPATH_GL11:
6373                 break;
6374         }
6375 }
6376
6377 #define SKINFRAME_HASH 1024
6378
6379 typedef struct
6380 {
6381         int loadsequence; // incremented each level change
6382         memexpandablearray_t array;
6383         skinframe_t *hash[SKINFRAME_HASH];
6384 }
6385 r_skinframe_t;
6386 r_skinframe_t r_skinframe;
6387
6388 void R_SkinFrame_PrepareForPurge(void)
6389 {
6390         r_skinframe.loadsequence++;
6391         // wrap it without hitting zero
6392         if (r_skinframe.loadsequence >= 200)
6393                 r_skinframe.loadsequence = 1;
6394 }
6395
6396 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6397 {
6398         if (!skinframe)
6399                 return;
6400         // mark the skinframe as used for the purging code
6401         skinframe->loadsequence = r_skinframe.loadsequence;
6402 }
6403
6404 void R_SkinFrame_Purge(void)
6405 {
6406         int i;
6407         skinframe_t *s;
6408         for (i = 0;i < SKINFRAME_HASH;i++)
6409         {
6410                 for (s = r_skinframe.hash[i];s;s = s->next)
6411                 {
6412                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6413                         {
6414                                 if (s->merged == s->base)
6415                                         s->merged = NULL;
6416                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6417                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6418                                 R_PurgeTexture(s->merged);s->merged = NULL;
6419                                 R_PurgeTexture(s->base  );s->base   = NULL;
6420                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6421                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6422                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6423                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6424                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6425                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6426                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6427                                 s->loadsequence = 0;
6428                         }
6429                 }
6430         }
6431 }
6432
6433 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6434         skinframe_t *item;
6435         char basename[MAX_QPATH];
6436
6437         Image_StripImageExtension(name, basename, sizeof(basename));
6438
6439         if( last == NULL ) {
6440                 int hashindex;
6441                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6442                 item = r_skinframe.hash[hashindex];
6443         } else {
6444                 item = last->next;
6445         }
6446
6447         // linearly search through the hash bucket
6448         for( ; item ; item = item->next ) {
6449                 if( !strcmp( item->basename, basename ) ) {
6450                         return item;
6451                 }
6452         }
6453         return NULL;
6454 }
6455
6456 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6457 {
6458         skinframe_t *item;
6459         int hashindex;
6460         char basename[MAX_QPATH];
6461
6462         Image_StripImageExtension(name, basename, sizeof(basename));
6463
6464         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6465         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6466                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6467                         break;
6468
6469         if (!item) {
6470                 rtexture_t *dyntexture;
6471                 // check whether its a dynamic texture
6472                 dyntexture = CL_GetDynTexture( basename );
6473                 if (!add && !dyntexture)
6474                         return NULL;
6475                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6476                 memset(item, 0, sizeof(*item));
6477                 strlcpy(item->basename, basename, sizeof(item->basename));
6478                 item->base = dyntexture; // either NULL or dyntexture handle
6479                 item->textureflags = textureflags;
6480                 item->comparewidth = comparewidth;
6481                 item->compareheight = compareheight;
6482                 item->comparecrc = comparecrc;
6483                 item->next = r_skinframe.hash[hashindex];
6484                 r_skinframe.hash[hashindex] = item;
6485         }
6486         else if( item->base == NULL )
6487         {
6488                 rtexture_t *dyntexture;
6489                 // check whether its a dynamic texture
6490                 // 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]
6491                 dyntexture = CL_GetDynTexture( basename );
6492                 item->base = dyntexture; // either NULL or dyntexture handle
6493         }
6494
6495         R_SkinFrame_MarkUsed(item);
6496         return item;
6497 }
6498
6499 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6500         { \
6501                 unsigned long long avgcolor[5], wsum; \
6502                 int pix, comp, w; \
6503                 avgcolor[0] = 0; \
6504                 avgcolor[1] = 0; \
6505                 avgcolor[2] = 0; \
6506                 avgcolor[3] = 0; \
6507                 avgcolor[4] = 0; \
6508                 wsum = 0; \
6509                 for(pix = 0; pix < cnt; ++pix) \
6510                 { \
6511                         w = 0; \
6512                         for(comp = 0; comp < 3; ++comp) \
6513                                 w += getpixel; \
6514                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6515                         { \
6516                                 ++wsum; \
6517                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6518                                 w = getpixel; \
6519                                 for(comp = 0; comp < 3; ++comp) \
6520                                         avgcolor[comp] += getpixel * w; \
6521                                 avgcolor[3] += w; \
6522                         } \
6523                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6524                         avgcolor[4] += getpixel; \
6525                 } \
6526                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6527                         avgcolor[3] = 1; \
6528                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6529                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6530                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6531                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6532         }
6533
6534 extern cvar_t gl_picmip;
6535 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6536 {
6537         int j;
6538         unsigned char *pixels;
6539         unsigned char *bumppixels;
6540         unsigned char *basepixels = NULL;
6541         int basepixels_width = 0;
6542         int basepixels_height = 0;
6543         skinframe_t *skinframe;
6544         rtexture_t *ddsbase = NULL;
6545         qboolean ddshasalpha = false;
6546         float ddsavgcolor[4];
6547         char basename[MAX_QPATH];
6548         int miplevel = R_PicmipForFlags(textureflags);
6549         int savemiplevel = miplevel;
6550         int mymiplevel;
6551
6552         if (cls.state == ca_dedicated)
6553                 return NULL;
6554
6555         // return an existing skinframe if already loaded
6556         // if loading of the first image fails, don't make a new skinframe as it
6557         // would cause all future lookups of this to be missing
6558         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6559         if (skinframe && skinframe->base)
6560                 return skinframe;
6561
6562         Image_StripImageExtension(name, basename, sizeof(basename));
6563
6564         // check for DDS texture file first
6565         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6566         {
6567                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6568                 if (basepixels == NULL)
6569                         return NULL;
6570         }
6571
6572         // FIXME handle miplevel
6573
6574         if (developer_loading.integer)
6575                 Con_Printf("loading skin \"%s\"\n", name);
6576
6577         // we've got some pixels to store, so really allocate this new texture now
6578         if (!skinframe)
6579                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6580         skinframe->stain = NULL;
6581         skinframe->merged = NULL;
6582         skinframe->base = NULL;
6583         skinframe->pants = NULL;
6584         skinframe->shirt = NULL;
6585         skinframe->nmap = NULL;
6586         skinframe->gloss = NULL;
6587         skinframe->glow = NULL;
6588         skinframe->fog = NULL;
6589         skinframe->reflect = NULL;
6590         skinframe->hasalpha = false;
6591
6592         if (ddsbase)
6593         {
6594                 skinframe->base = ddsbase;
6595                 skinframe->hasalpha = ddshasalpha;
6596                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6597                 if (r_loadfog && skinframe->hasalpha)
6598                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6599                 //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]);
6600         }
6601         else
6602         {
6603                 basepixels_width = image_width;
6604                 basepixels_height = image_height;
6605                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6606                 if (textureflags & TEXF_ALPHA)
6607                 {
6608                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6609                         {
6610                                 if (basepixels[j] < 255)
6611                                 {
6612                                         skinframe->hasalpha = true;
6613                                         break;
6614                                 }
6615                         }
6616                         if (r_loadfog && skinframe->hasalpha)
6617                         {
6618                                 // has transparent pixels
6619                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6620                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6621                                 {
6622                                         pixels[j+0] = 255;
6623                                         pixels[j+1] = 255;
6624                                         pixels[j+2] = 255;
6625                                         pixels[j+3] = basepixels[j+3];
6626                                 }
6627                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
6628                                 Mem_Free(pixels);
6629                         }
6630                 }
6631                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6632                 //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]);
6633                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6634                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6635                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6636                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6637         }
6638
6639         if (r_loaddds)
6640         {
6641                 mymiplevel = savemiplevel;
6642                 if (r_loadnormalmap)
6643                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
6644                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6645                 if (r_loadgloss)
6646                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6647                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6648                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6649                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6650         }
6651
6652         // _norm is the name used by tenebrae and has been adopted as standard
6653         if (r_loadnormalmap && skinframe->nmap == NULL)
6654         {
6655                 mymiplevel = savemiplevel;
6656                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6657                 {
6658                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6659                         Mem_Free(pixels);
6660                         pixels = NULL;
6661                 }
6662                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6663                 {
6664                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6665                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6666                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6667                         Mem_Free(pixels);
6668                         Mem_Free(bumppixels);
6669                 }
6670                 else if (r_shadow_bumpscale_basetexture.value > 0)
6671                 {
6672                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6673                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6674                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6675                         Mem_Free(pixels);
6676                 }
6677                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6678                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6679         }
6680
6681         // _luma is supported only for tenebrae compatibility
6682         // _glow is the preferred name
6683         mymiplevel = savemiplevel;
6684         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
6685         {
6686                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6687                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6688                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6689                 Mem_Free(pixels);pixels = NULL;
6690         }
6691
6692         mymiplevel = savemiplevel;
6693         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6694         {
6695                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6696                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6697                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6698                 Mem_Free(pixels);
6699                 pixels = NULL;
6700         }
6701
6702         mymiplevel = savemiplevel;
6703         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6704         {
6705                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6706                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6707                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6708                 Mem_Free(pixels);
6709                 pixels = NULL;
6710         }
6711
6712         mymiplevel = savemiplevel;
6713         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6714         {
6715                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6716                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6717                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6718                 Mem_Free(pixels);
6719                 pixels = NULL;
6720         }
6721
6722         mymiplevel = savemiplevel;
6723         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6724         {
6725                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
6726                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6727                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6728                 Mem_Free(pixels);
6729                 pixels = NULL;
6730         }
6731
6732         if (basepixels)
6733                 Mem_Free(basepixels);
6734
6735         return skinframe;
6736 }
6737
6738 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6739 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6740 {
6741         int i;
6742         unsigned char *temp1, *temp2;
6743         skinframe_t *skinframe;
6744
6745         if (cls.state == ca_dedicated)
6746                 return NULL;
6747
6748         // if already loaded just return it, otherwise make a new skinframe
6749         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6750         if (skinframe && skinframe->base)
6751                 return skinframe;
6752
6753         skinframe->stain = NULL;
6754         skinframe->merged = NULL;
6755         skinframe->base = NULL;
6756         skinframe->pants = NULL;
6757         skinframe->shirt = NULL;
6758         skinframe->nmap = NULL;
6759         skinframe->gloss = NULL;
6760         skinframe->glow = NULL;
6761         skinframe->fog = NULL;
6762         skinframe->reflect = NULL;
6763         skinframe->hasalpha = false;
6764
6765         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6766         if (!skindata)
6767                 return NULL;
6768
6769         if (developer_loading.integer)
6770                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6771
6772         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6773         {
6774                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6775                 temp2 = temp1 + width * height * 4;
6776                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6777                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6778                 Mem_Free(temp1);
6779         }
6780         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6781         if (textureflags & TEXF_ALPHA)
6782         {
6783                 for (i = 3;i < width * height * 4;i += 4)
6784                 {
6785                         if (skindata[i] < 255)
6786                         {
6787                                 skinframe->hasalpha = true;
6788                                 break;
6789                         }
6790                 }
6791                 if (r_loadfog && skinframe->hasalpha)
6792                 {
6793                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6794                         memcpy(fogpixels, skindata, width * height * 4);
6795                         for (i = 0;i < width * height * 4;i += 4)
6796                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6797                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6798                         Mem_Free(fogpixels);
6799                 }
6800         }
6801
6802         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6803         //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]);
6804
6805         return skinframe;
6806 }
6807
6808 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6809 {
6810         int i;
6811         int featuresmask;
6812         skinframe_t *skinframe;
6813
6814         if (cls.state == ca_dedicated)
6815                 return NULL;
6816
6817         // if already loaded just return it, otherwise make a new skinframe
6818         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6819         if (skinframe && skinframe->base)
6820                 return skinframe;
6821
6822         skinframe->stain = NULL;
6823         skinframe->merged = NULL;
6824         skinframe->base = NULL;
6825         skinframe->pants = NULL;
6826         skinframe->shirt = NULL;
6827         skinframe->nmap = NULL;
6828         skinframe->gloss = NULL;
6829         skinframe->glow = NULL;
6830         skinframe->fog = NULL;
6831         skinframe->reflect = NULL;
6832         skinframe->hasalpha = false;
6833
6834         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6835         if (!skindata)
6836                 return NULL;
6837
6838         if (developer_loading.integer)
6839                 Con_Printf("loading quake skin \"%s\"\n", name);
6840
6841         // 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)
6842         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6843         memcpy(skinframe->qpixels, skindata, width*height);
6844         skinframe->qwidth = width;
6845         skinframe->qheight = height;
6846
6847         featuresmask = 0;
6848         for (i = 0;i < width * height;i++)
6849                 featuresmask |= palette_featureflags[skindata[i]];
6850
6851         skinframe->hasalpha = false;
6852         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6853         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6854         skinframe->qgeneratemerged = true;
6855         skinframe->qgeneratebase = skinframe->qhascolormapping;
6856         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6857
6858         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6859         //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]);
6860
6861         return skinframe;
6862 }
6863
6864 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6865 {
6866         int width;
6867         int height;
6868         unsigned char *skindata;
6869
6870         if (!skinframe->qpixels)
6871                 return;
6872
6873         if (!skinframe->qhascolormapping)
6874                 colormapped = false;
6875
6876         if (colormapped)
6877         {
6878                 if (!skinframe->qgeneratebase)
6879                         return;
6880         }
6881         else
6882         {
6883                 if (!skinframe->qgeneratemerged)
6884                         return;
6885         }
6886
6887         width = skinframe->qwidth;
6888         height = skinframe->qheight;
6889         skindata = skinframe->qpixels;
6890
6891         if (skinframe->qgeneratenmap)
6892         {
6893                 unsigned char *temp1, *temp2;
6894                 skinframe->qgeneratenmap = false;
6895                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6896                 temp2 = temp1 + width * height * 4;
6897                 // use either a custom palette or the quake palette
6898                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6899                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6900                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
6901                 Mem_Free(temp1);
6902         }
6903
6904         if (skinframe->qgenerateglow)
6905         {
6906                 skinframe->qgenerateglow = false;
6907                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6908         }
6909
6910         if (colormapped)
6911         {
6912                 skinframe->qgeneratebase = false;
6913                 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);
6914                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6915                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6916         }
6917         else
6918         {
6919                 skinframe->qgeneratemerged = false;
6920                 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);
6921         }
6922
6923         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6924         {
6925                 Mem_Free(skinframe->qpixels);
6926                 skinframe->qpixels = NULL;
6927         }
6928 }
6929
6930 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)
6931 {
6932         int i;
6933         skinframe_t *skinframe;
6934
6935         if (cls.state == ca_dedicated)
6936                 return NULL;
6937
6938         // if already loaded just return it, otherwise make a new skinframe
6939         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6940         if (skinframe && skinframe->base)
6941                 return skinframe;
6942
6943         skinframe->stain = NULL;
6944         skinframe->merged = NULL;
6945         skinframe->base = NULL;
6946         skinframe->pants = NULL;
6947         skinframe->shirt = NULL;
6948         skinframe->nmap = NULL;
6949         skinframe->gloss = NULL;
6950         skinframe->glow = NULL;
6951         skinframe->fog = NULL;
6952         skinframe->reflect = NULL;
6953         skinframe->hasalpha = false;
6954
6955         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6956         if (!skindata)
6957                 return NULL;
6958
6959         if (developer_loading.integer)
6960                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6961
6962         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6963         if (textureflags & TEXF_ALPHA)
6964         {
6965                 for (i = 0;i < width * height;i++)
6966                 {
6967                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6968                         {
6969                                 skinframe->hasalpha = true;
6970                                 break;
6971                         }
6972                 }
6973                 if (r_loadfog && skinframe->hasalpha)
6974                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6975         }
6976
6977         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6978         //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]);
6979
6980         return skinframe;
6981 }
6982
6983 skinframe_t *R_SkinFrame_LoadMissing(void)
6984 {
6985         skinframe_t *skinframe;
6986
6987         if (cls.state == ca_dedicated)
6988                 return NULL;
6989
6990         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6991         skinframe->stain = NULL;
6992         skinframe->merged = NULL;
6993         skinframe->base = NULL;
6994         skinframe->pants = NULL;
6995         skinframe->shirt = NULL;
6996         skinframe->nmap = NULL;
6997         skinframe->gloss = NULL;
6998         skinframe->glow = NULL;
6999         skinframe->fog = NULL;
7000         skinframe->reflect = NULL;
7001         skinframe->hasalpha = false;
7002
7003         skinframe->avgcolor[0] = rand() / RAND_MAX;
7004         skinframe->avgcolor[1] = rand() / RAND_MAX;
7005         skinframe->avgcolor[2] = rand() / RAND_MAX;
7006         skinframe->avgcolor[3] = 1;
7007
7008         return skinframe;
7009 }
7010
7011 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7012 typedef struct suffixinfo_s
7013 {
7014         const char *suffix;
7015         qboolean flipx, flipy, flipdiagonal;
7016 }
7017 suffixinfo_t;
7018 static suffixinfo_t suffix[3][6] =
7019 {
7020         {
7021                 {"px",   false, false, false},
7022                 {"nx",   false, false, false},
7023                 {"py",   false, false, false},
7024                 {"ny",   false, false, false},
7025                 {"pz",   false, false, false},
7026                 {"nz",   false, false, false}
7027         },
7028         {
7029                 {"posx", false, false, false},
7030                 {"negx", false, false, false},
7031                 {"posy", false, false, false},
7032                 {"negy", false, false, false},
7033                 {"posz", false, false, false},
7034                 {"negz", false, false, false}
7035         },
7036         {
7037                 {"rt",    true, false,  true},
7038                 {"lf",   false,  true,  true},
7039                 {"ft",    true,  true, false},
7040                 {"bk",   false, false, false},
7041                 {"up",    true, false,  true},
7042                 {"dn",    true, false,  true}
7043         }
7044 };
7045
7046 static int componentorder[4] = {0, 1, 2, 3};
7047
7048 rtexture_t *R_LoadCubemap(const char *basename)
7049 {
7050         int i, j, cubemapsize;
7051         unsigned char *cubemappixels, *image_buffer;
7052         rtexture_t *cubemaptexture;
7053         char name[256];
7054         // must start 0 so the first loadimagepixels has no requested width/height
7055         cubemapsize = 0;
7056         cubemappixels = NULL;
7057         cubemaptexture = NULL;
7058         // keep trying different suffix groups (posx, px, rt) until one loads
7059         for (j = 0;j < 3 && !cubemappixels;j++)
7060         {
7061                 // load the 6 images in the suffix group
7062                 for (i = 0;i < 6;i++)
7063                 {
7064                         // generate an image name based on the base and and suffix
7065                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7066                         // load it
7067                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7068                         {
7069                                 // an image loaded, make sure width and height are equal
7070                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7071                                 {
7072                                         // if this is the first image to load successfully, allocate the cubemap memory
7073                                         if (!cubemappixels && image_width >= 1)
7074                                         {
7075                                                 cubemapsize = image_width;
7076                                                 // note this clears to black, so unavailable sides are black
7077                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7078                                         }
7079                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7080                                         if (cubemappixels)
7081                                                 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);
7082                                 }
7083                                 else
7084                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7085                                 // free the image
7086                                 Mem_Free(image_buffer);
7087                         }
7088                 }
7089         }
7090         // if a cubemap loaded, upload it
7091         if (cubemappixels)
7092         {
7093                 if (developer_loading.integer)
7094                         Con_Printf("loading cubemap \"%s\"\n", basename);
7095
7096                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7097                 Mem_Free(cubemappixels);
7098         }
7099         else
7100         {
7101                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7102                 if (developer_loading.integer)
7103                 {
7104                         Con_Printf("(tried tried images ");
7105                         for (j = 0;j < 3;j++)
7106                                 for (i = 0;i < 6;i++)
7107                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7108                         Con_Print(" and was unable to find any of them).\n");
7109                 }
7110         }
7111         return cubemaptexture;
7112 }
7113
7114 rtexture_t *R_GetCubemap(const char *basename)
7115 {
7116         int i;
7117         for (i = 0;i < r_texture_numcubemaps;i++)
7118                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7119                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7120         if (i >= MAX_CUBEMAPS)
7121                 return r_texture_whitecube;
7122         r_texture_numcubemaps++;
7123         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7124         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7125         return r_texture_cubemaps[i].texture;
7126 }
7127
7128 void R_FreeCubemaps(void)
7129 {
7130         int i;
7131         for (i = 0;i < r_texture_numcubemaps;i++)
7132         {
7133                 if (developer_loading.integer)
7134                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7135                 if (r_texture_cubemaps[i].texture)
7136                         R_FreeTexture(r_texture_cubemaps[i].texture);
7137         }
7138         r_texture_numcubemaps = 0;
7139 }
7140
7141 void R_Main_FreeViewCache(void)
7142 {
7143         if (r_refdef.viewcache.entityvisible)
7144                 Mem_Free(r_refdef.viewcache.entityvisible);
7145         if (r_refdef.viewcache.world_pvsbits)
7146                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7147         if (r_refdef.viewcache.world_leafvisible)
7148                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7149         if (r_refdef.viewcache.world_surfacevisible)
7150                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7151         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7152 }
7153
7154 void R_Main_ResizeViewCache(void)
7155 {
7156         int numentities = r_refdef.scene.numentities;
7157         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7158         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7159         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7160         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7161         if (r_refdef.viewcache.maxentities < numentities)
7162         {
7163                 r_refdef.viewcache.maxentities = numentities;
7164                 if (r_refdef.viewcache.entityvisible)
7165                         Mem_Free(r_refdef.viewcache.entityvisible);
7166                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7167         }
7168         if (r_refdef.viewcache.world_numclusters != numclusters)
7169         {
7170                 r_refdef.viewcache.world_numclusters = numclusters;
7171                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7172                 if (r_refdef.viewcache.world_pvsbits)
7173                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7174                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7175         }
7176         if (r_refdef.viewcache.world_numleafs != numleafs)
7177         {
7178                 r_refdef.viewcache.world_numleafs = numleafs;
7179                 if (r_refdef.viewcache.world_leafvisible)
7180                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7181                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7182         }
7183         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7184         {
7185                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7186                 if (r_refdef.viewcache.world_surfacevisible)
7187                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7188                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7189         }
7190 }
7191
7192 extern rtexture_t *loadingscreentexture;
7193 void gl_main_start(void)
7194 {
7195         loadingscreentexture = NULL;
7196         r_texture_blanknormalmap = NULL;
7197         r_texture_white = NULL;
7198         r_texture_grey128 = NULL;
7199         r_texture_black = NULL;
7200         r_texture_whitecube = NULL;
7201         r_texture_normalizationcube = NULL;
7202         r_texture_fogattenuation = NULL;
7203         r_texture_fogheighttexture = NULL;
7204         r_texture_gammaramps = NULL;
7205         r_texture_numcubemaps = 0;
7206
7207         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
7208         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7209
7210         switch(vid.renderpath)
7211         {
7212         case RENDERPATH_GL20:
7213         case RENDERPATH_CGGL:
7214         case RENDERPATH_D3D9:
7215         case RENDERPATH_D3D10:
7216         case RENDERPATH_D3D11:
7217                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7218                 Cvar_SetValueQuick(&gl_combine, 1);
7219                 Cvar_SetValueQuick(&r_glsl, 1);
7220                 r_loadnormalmap = true;
7221                 r_loadgloss = true;
7222                 r_loadfog = false;
7223                 break;
7224         case RENDERPATH_GL13:
7225                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7226                 Cvar_SetValueQuick(&gl_combine, 1);
7227                 Cvar_SetValueQuick(&r_glsl, 0);
7228                 r_loadnormalmap = false;
7229                 r_loadgloss = false;
7230                 r_loadfog = true;
7231                 break;
7232         case RENDERPATH_GL11:
7233                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7234                 Cvar_SetValueQuick(&gl_combine, 0);
7235                 Cvar_SetValueQuick(&r_glsl, 0);
7236                 r_loadnormalmap = false;
7237                 r_loadgloss = false;
7238                 r_loadfog = true;
7239                 break;
7240         }
7241
7242         R_AnimCache_Free();
7243         R_FrameData_Reset();
7244
7245         r_numqueries = 0;
7246         r_maxqueries = 0;
7247         memset(r_queries, 0, sizeof(r_queries));
7248
7249         r_qwskincache = NULL;
7250         r_qwskincache_size = 0;
7251
7252         // set up r_skinframe loading system for textures
7253         memset(&r_skinframe, 0, sizeof(r_skinframe));
7254         r_skinframe.loadsequence = 1;
7255         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7256
7257         r_main_texturepool = R_AllocTexturePool();
7258         R_BuildBlankTextures();
7259         R_BuildNoTexture();
7260         if (vid.support.arb_texture_cube_map)
7261         {
7262                 R_BuildWhiteCube();
7263                 R_BuildNormalizationCube();
7264         }
7265         r_texture_fogattenuation = NULL;
7266         r_texture_fogheighttexture = NULL;
7267         r_texture_gammaramps = NULL;
7268         //r_texture_fogintensity = NULL;
7269         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7270         memset(&r_waterstate, 0, sizeof(r_waterstate));
7271         r_glsl_permutation = NULL;
7272         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7273         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7274         glslshaderstring = NULL;
7275 #ifdef SUPPORTCG
7276         r_cg_permutation = NULL;
7277         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7278         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7279         cgshaderstring = NULL;
7280 #endif
7281 #ifdef SUPPORTD3D
7282         r_hlsl_permutation = NULL;
7283         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7284         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7285         hlslshaderstring = NULL;
7286 #endif
7287         memset(&r_svbsp, 0, sizeof (r_svbsp));
7288
7289         r_refdef.fogmasktable_density = 0;
7290 }
7291
7292 void gl_main_shutdown(void)
7293 {
7294         R_AnimCache_Free();
7295         R_FrameData_Reset();
7296
7297         R_Main_FreeViewCache();
7298
7299         switch(vid.renderpath)
7300         {
7301         case RENDERPATH_GL11:
7302         case RENDERPATH_GL13:
7303         case RENDERPATH_GL20:
7304         case RENDERPATH_CGGL:
7305                 if (r_maxqueries)
7306                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7307                 break;
7308         case RENDERPATH_D3D9:
7309                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7310                 break;
7311         case RENDERPATH_D3D10:
7312                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7313                 break;
7314         case RENDERPATH_D3D11:
7315                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7316                 break;
7317         }
7318
7319         r_numqueries = 0;
7320         r_maxqueries = 0;
7321         memset(r_queries, 0, sizeof(r_queries));
7322
7323         r_qwskincache = NULL;
7324         r_qwskincache_size = 0;
7325
7326         // clear out the r_skinframe state
7327         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7328         memset(&r_skinframe, 0, sizeof(r_skinframe));
7329
7330         if (r_svbsp.nodes)
7331                 Mem_Free(r_svbsp.nodes);
7332         memset(&r_svbsp, 0, sizeof (r_svbsp));
7333         R_FreeTexturePool(&r_main_texturepool);
7334         loadingscreentexture = NULL;
7335         r_texture_blanknormalmap = NULL;
7336         r_texture_white = NULL;
7337         r_texture_grey128 = NULL;
7338         r_texture_black = NULL;
7339         r_texture_whitecube = NULL;
7340         r_texture_normalizationcube = NULL;
7341         r_texture_fogattenuation = NULL;
7342         r_texture_fogheighttexture = NULL;
7343         r_texture_gammaramps = NULL;
7344         r_texture_numcubemaps = 0;
7345         //r_texture_fogintensity = NULL;
7346         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7347         memset(&r_waterstate, 0, sizeof(r_waterstate));
7348         R_GLSL_Restart_f();
7349 }
7350
7351 extern void CL_ParseEntityLump(char *entitystring);
7352 void gl_main_newmap(void)
7353 {
7354         // FIXME: move this code to client
7355         char *entities, entname[MAX_QPATH];
7356         if (r_qwskincache)
7357                 Mem_Free(r_qwskincache);
7358         r_qwskincache = NULL;
7359         r_qwskincache_size = 0;
7360         if (cl.worldmodel)
7361         {
7362                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7363                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7364                 {
7365                         CL_ParseEntityLump(entities);
7366                         Mem_Free(entities);
7367                         return;
7368                 }
7369                 if (cl.worldmodel->brush.entities)
7370                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7371         }
7372         R_Main_FreeViewCache();
7373
7374         R_FrameData_Reset();
7375 }
7376
7377 void GL_Main_Init(void)
7378 {
7379         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7380
7381         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7382         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7383         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7384         if (gamemode == GAME_NEHAHRA)
7385         {
7386                 Cvar_RegisterVariable (&gl_fogenable);
7387                 Cvar_RegisterVariable (&gl_fogdensity);
7388                 Cvar_RegisterVariable (&gl_fogred);
7389                 Cvar_RegisterVariable (&gl_foggreen);
7390                 Cvar_RegisterVariable (&gl_fogblue);
7391                 Cvar_RegisterVariable (&gl_fogstart);
7392                 Cvar_RegisterVariable (&gl_fogend);
7393                 Cvar_RegisterVariable (&gl_skyclip);
7394         }
7395         Cvar_RegisterVariable(&r_motionblur);
7396         Cvar_RegisterVariable(&r_motionblur_maxblur);
7397         Cvar_RegisterVariable(&r_motionblur_bmin);
7398         Cvar_RegisterVariable(&r_motionblur_vmin);
7399         Cvar_RegisterVariable(&r_motionblur_vmax);
7400         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7401         Cvar_RegisterVariable(&r_motionblur_randomize);
7402         Cvar_RegisterVariable(&r_damageblur);
7403         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7404         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7405         Cvar_RegisterVariable(&r_equalize_entities_by);
7406         Cvar_RegisterVariable(&r_equalize_entities_to);
7407         Cvar_RegisterVariable(&r_depthfirst);
7408         Cvar_RegisterVariable(&r_useinfinitefarclip);
7409         Cvar_RegisterVariable(&r_farclip_base);
7410         Cvar_RegisterVariable(&r_farclip_world);
7411         Cvar_RegisterVariable(&r_nearclip);
7412         Cvar_RegisterVariable(&r_showbboxes);
7413         Cvar_RegisterVariable(&r_showsurfaces);
7414         Cvar_RegisterVariable(&r_showtris);
7415         Cvar_RegisterVariable(&r_shownormals);
7416         Cvar_RegisterVariable(&r_showlighting);
7417         Cvar_RegisterVariable(&r_showshadowvolumes);
7418         Cvar_RegisterVariable(&r_showcollisionbrushes);
7419         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7420         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7421         Cvar_RegisterVariable(&r_showdisabledepthtest);
7422         Cvar_RegisterVariable(&r_drawportals);
7423         Cvar_RegisterVariable(&r_drawentities);
7424         Cvar_RegisterVariable(&r_draw2d);
7425         Cvar_RegisterVariable(&r_drawworld);
7426         Cvar_RegisterVariable(&r_cullentities_trace);
7427         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7428         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7429         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7430         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7431         Cvar_RegisterVariable(&r_drawviewmodel);
7432         Cvar_RegisterVariable(&r_drawexteriormodel);
7433         Cvar_RegisterVariable(&r_speeds);
7434         Cvar_RegisterVariable(&r_fullbrights);
7435         Cvar_RegisterVariable(&r_wateralpha);
7436         Cvar_RegisterVariable(&r_dynamic);
7437         Cvar_RegisterVariable(&r_fullbright);
7438         Cvar_RegisterVariable(&r_shadows);
7439         Cvar_RegisterVariable(&r_shadows_darken);
7440         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7441         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7442         Cvar_RegisterVariable(&r_shadows_throwdistance);
7443         Cvar_RegisterVariable(&r_shadows_throwdirection);
7444         Cvar_RegisterVariable(&r_shadows_focus);
7445         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7446         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7447         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7448         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7449         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7450         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7451         Cvar_RegisterVariable(&r_fog_exp2);
7452         Cvar_RegisterVariable(&r_drawfog);
7453         Cvar_RegisterVariable(&r_transparentdepthmasking);
7454         Cvar_RegisterVariable(&r_texture_dds_load);
7455         Cvar_RegisterVariable(&r_texture_dds_save);
7456         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7457         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7458         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7459         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7460         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7461         Cvar_RegisterVariable(&r_textureunits);
7462         Cvar_RegisterVariable(&gl_combine);
7463         Cvar_RegisterVariable(&r_glsl);
7464         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7465         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7466         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7467         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7468         Cvar_RegisterVariable(&r_glsl_postprocess);
7469         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7470         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7471         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7472         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7473         Cvar_RegisterVariable(&r_water);
7474         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7475         Cvar_RegisterVariable(&r_water_clippingplanebias);
7476         Cvar_RegisterVariable(&r_water_refractdistort);
7477         Cvar_RegisterVariable(&r_water_reflectdistort);
7478         Cvar_RegisterVariable(&r_lerpsprites);
7479         Cvar_RegisterVariable(&r_lerpmodels);
7480         Cvar_RegisterVariable(&r_lerplightstyles);
7481         Cvar_RegisterVariable(&r_waterscroll);
7482         Cvar_RegisterVariable(&r_bloom);
7483         Cvar_RegisterVariable(&r_bloom_colorscale);
7484         Cvar_RegisterVariable(&r_bloom_brighten);
7485         Cvar_RegisterVariable(&r_bloom_blur);
7486         Cvar_RegisterVariable(&r_bloom_resolution);
7487         Cvar_RegisterVariable(&r_bloom_colorexponent);
7488         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7489         Cvar_RegisterVariable(&r_hdr);
7490         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7491         Cvar_RegisterVariable(&r_hdr_glowintensity);
7492         Cvar_RegisterVariable(&r_hdr_range);
7493         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7494         Cvar_RegisterVariable(&developer_texturelogging);
7495         Cvar_RegisterVariable(&gl_lightmaps);
7496         Cvar_RegisterVariable(&r_test);
7497         Cvar_RegisterVariable(&r_glsl_saturation);
7498         Cvar_RegisterVariable(&r_framedatasize);
7499         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7500                 Cvar_SetValue("r_fullbrights", 0);
7501         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7502
7503         Cvar_RegisterVariable(&r_track_sprites);
7504         Cvar_RegisterVariable(&r_track_sprites_flags);
7505         Cvar_RegisterVariable(&r_track_sprites_scalew);
7506         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7507         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7508         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7509 }
7510
7511 extern void R_Textures_Init(void);
7512 extern void GL_Draw_Init(void);
7513 extern void GL_Main_Init(void);
7514 extern void R_Shadow_Init(void);
7515 extern void R_Sky_Init(void);
7516 extern void GL_Surf_Init(void);
7517 extern void R_Particles_Init(void);
7518 extern void R_Explosion_Init(void);
7519 extern void gl_backend_init(void);
7520 extern void Sbar_Init(void);
7521 extern void R_LightningBeams_Init(void);
7522 extern void Mod_RenderInit(void);
7523 extern void Font_Init(void);
7524
7525 void Render_Init(void)
7526 {
7527         gl_backend_init();
7528         R_Textures_Init();
7529         GL_Main_Init();
7530         Font_Init();
7531         GL_Draw_Init();
7532         R_Shadow_Init();
7533         R_Sky_Init();
7534         GL_Surf_Init();
7535         Sbar_Init();
7536         R_Particles_Init();
7537         R_Explosion_Init();
7538         R_LightningBeams_Init();
7539         Mod_RenderInit();
7540 }
7541
7542 /*
7543 ===============
7544 GL_Init
7545 ===============
7546 */
7547 extern char *ENGINE_EXTENSIONS;
7548 void GL_Init (void)
7549 {
7550         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7551         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7552         gl_version = (const char *)qglGetString(GL_VERSION);
7553         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7554
7555         if (!gl_extensions)
7556                 gl_extensions = "";
7557         if (!gl_platformextensions)
7558                 gl_platformextensions = "";
7559
7560         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7561         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7562         Con_Printf("GL_VERSION: %s\n", gl_version);
7563         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7564         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7565
7566         VID_CheckExtensions();
7567
7568         // LordHavoc: report supported extensions
7569         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7570
7571         // clear to black (loading plaque will be seen over this)
7572         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7573 }
7574
7575 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7576 {
7577         int i;
7578         mplane_t *p;
7579         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7580         {
7581                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7582                 if (i == 4)
7583                         continue;
7584                 p = r_refdef.view.frustum + i;
7585                 switch(p->signbits)
7586                 {
7587                 default:
7588                 case 0:
7589                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7590                                 return true;
7591                         break;
7592                 case 1:
7593                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7594                                 return true;
7595                         break;
7596                 case 2:
7597                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7598                                 return true;
7599                         break;
7600                 case 3:
7601                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7602                                 return true;
7603                         break;
7604                 case 4:
7605                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7606                                 return true;
7607                         break;
7608                 case 5:
7609                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7610                                 return true;
7611                         break;
7612                 case 6:
7613                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7614                                 return true;
7615                         break;
7616                 case 7:
7617                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7618                                 return true;
7619                         break;
7620                 }
7621         }
7622         return false;
7623 }
7624
7625 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7626 {
7627         int i;
7628         const mplane_t *p;
7629         for (i = 0;i < numplanes;i++)
7630         {
7631                 p = planes + i;
7632                 switch(p->signbits)
7633                 {
7634                 default:
7635                 case 0:
7636                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7637                                 return true;
7638                         break;
7639                 case 1:
7640                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7641                                 return true;
7642                         break;
7643                 case 2:
7644                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7645                                 return true;
7646                         break;
7647                 case 3:
7648                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7649                                 return true;
7650                         break;
7651                 case 4:
7652                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7653                                 return true;
7654                         break;
7655                 case 5:
7656                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7657                                 return true;
7658                         break;
7659                 case 6:
7660                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7661                                 return true;
7662                         break;
7663                 case 7:
7664                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7665                                 return true;
7666                         break;
7667                 }
7668         }
7669         return false;
7670 }
7671
7672 //==================================================================================
7673
7674 // LordHavoc: this stores temporary data used within the same frame
7675
7676 qboolean r_framedata_failed;
7677 static size_t r_framedata_size;
7678 static size_t r_framedata_current;
7679 static void *r_framedata_base;
7680
7681 void R_FrameData_Reset(void)
7682 {
7683         if (r_framedata_base)
7684                 Mem_Free(r_framedata_base);
7685         r_framedata_base = NULL;
7686         r_framedata_size = 0;
7687         r_framedata_current = 0;
7688         r_framedata_failed = false;
7689 }
7690
7691 void R_FrameData_NewFrame(void)
7692 {
7693         size_t wantedsize;
7694         if (r_framedata_failed)
7695                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7696         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7697         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7698         if (r_framedata_size != wantedsize)
7699         {
7700                 r_framedata_size = wantedsize;
7701                 if (r_framedata_base)
7702                         Mem_Free(r_framedata_base);
7703                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7704         }
7705         r_framedata_current = 0;
7706         r_framedata_failed = false;
7707 }
7708
7709 void *R_FrameData_Alloc(size_t size)
7710 {
7711         void *data;
7712
7713         // align to 16 byte boundary
7714         size = (size + 15) & ~15;
7715         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7716         r_framedata_current += size;
7717
7718         // check overflow
7719         if (r_framedata_current > r_framedata_size)
7720                 r_framedata_failed = true;
7721
7722         // return NULL on everything after a failure
7723         if (r_framedata_failed)
7724                 return NULL;
7725
7726         return data;
7727 }
7728
7729 void *R_FrameData_Store(size_t size, void *data)
7730 {
7731         void *d = R_FrameData_Alloc(size);
7732         if (d)
7733                 memcpy(d, data, size);
7734         return d;
7735 }
7736
7737 //==================================================================================
7738
7739 // LordHavoc: animcache originally written by Echon, rewritten since then
7740
7741 /**
7742  * Animation cache prevents re-generating mesh data for an animated model
7743  * multiple times in one frame for lighting, shadowing, reflections, etc.
7744  */
7745
7746 void R_AnimCache_Free(void)
7747 {
7748 }
7749
7750 void R_AnimCache_ClearCache(void)
7751 {
7752         int i;
7753         entity_render_t *ent;
7754
7755         for (i = 0;i < r_refdef.scene.numentities;i++)
7756         {
7757                 ent = r_refdef.scene.entities[i];
7758                 ent->animcache_vertex3f = NULL;
7759                 ent->animcache_normal3f = NULL;
7760                 ent->animcache_svector3f = NULL;
7761                 ent->animcache_tvector3f = NULL;
7762                 ent->animcache_vertexposition = NULL;
7763                 ent->animcache_vertexmesh = NULL;
7764                 ent->animcache_vertexpositionbuffer = NULL;
7765                 ent->animcache_vertexmeshbuffer = NULL;
7766         }
7767 }
7768
7769 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7770 {
7771         int i;
7772
7773         // identical memory layout, so no need to allocate...
7774         // this also provides the vertexposition structure to everything, e.g.
7775         // depth masked rendering currently uses it even if having separate
7776         // arrays
7777         // NOTE: get rid of this optimization if changing it to e.g. 4f
7778         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7779
7780         // TODO:
7781         // get rid of following uses of VERTEXPOSITION, change to the array:
7782         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7783         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7784         // R_DrawTextureSurfaceList_DepthOnly
7785         // R_Q1BSP_DrawShadowMap
7786
7787         switch(vid.renderpath)
7788         {
7789         case RENDERPATH_GL20:
7790         case RENDERPATH_CGGL:
7791                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7792                 if (gl_mesh_separatearrays.integer)
7793                         return;
7794                 break;
7795         case RENDERPATH_D3D9:
7796         case RENDERPATH_D3D10:
7797         case RENDERPATH_D3D11:
7798                 // always need the meshbuffers
7799                 break;
7800         case RENDERPATH_GL13:
7801         case RENDERPATH_GL11:
7802                 // never need the meshbuffers
7803                 return;
7804         }
7805
7806         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7807                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7808         /*
7809         if (!ent->animcache_vertexposition)
7810                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7811         */
7812         if (ent->animcache_vertexposition)
7813         {
7814                 /*
7815                 for (i = 0;i < numvertices;i++)
7816                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7817                 */
7818                 // TODO: upload vertex buffer?
7819         }
7820         if (ent->animcache_vertexmesh)
7821         {
7822                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7823                 for (i = 0;i < numvertices;i++)
7824                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7825                 if (ent->animcache_svector3f)
7826                         for (i = 0;i < numvertices;i++)
7827                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7828                 if (ent->animcache_tvector3f)
7829                         for (i = 0;i < numvertices;i++)
7830                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7831                 if (ent->animcache_normal3f)
7832                         for (i = 0;i < numvertices;i++)
7833                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7834                 // TODO: upload vertex buffer?
7835         }
7836 }
7837
7838 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7839 {
7840         dp_model_t *model = ent->model;
7841         int numvertices;
7842         // see if it's already cached this frame
7843         if (ent->animcache_vertex3f)
7844         {
7845                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7846                 if (wantnormals || wanttangents)
7847                 {
7848                         if (ent->animcache_normal3f)
7849                                 wantnormals = false;
7850                         if (ent->animcache_svector3f)
7851                                 wanttangents = false;
7852                         if (wantnormals || wanttangents)
7853                         {
7854                                 numvertices = model->surfmesh.num_vertices;
7855                                 if (wantnormals)
7856                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7857                                 if (wanttangents)
7858                                 {
7859                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7860                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7861                                 }
7862                                 if (!r_framedata_failed)
7863                                 {
7864                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7865                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7866                                 }
7867                         }
7868                 }
7869         }
7870         else
7871         {
7872                 // see if this ent is worth caching
7873                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7874                         return false;
7875                 // get some memory for this entity and generate mesh data
7876                 numvertices = model->surfmesh.num_vertices;
7877                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7878                 if (wantnormals)
7879                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7880                 if (wanttangents)
7881                 {
7882                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7883                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7884                 }
7885                 if (!r_framedata_failed)
7886                 {
7887                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7888                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7889                 }
7890         }
7891         return !r_framedata_failed;
7892 }
7893
7894 void R_AnimCache_CacheVisibleEntities(void)
7895 {
7896         int i;
7897         qboolean wantnormals = true;
7898         qboolean wanttangents = !r_showsurfaces.integer;
7899
7900         switch(vid.renderpath)
7901         {
7902         case RENDERPATH_GL20:
7903         case RENDERPATH_CGGL:
7904         case RENDERPATH_D3D9:
7905         case RENDERPATH_D3D10:
7906         case RENDERPATH_D3D11:
7907                 break;
7908         case RENDERPATH_GL13:
7909         case RENDERPATH_GL11:
7910                 wanttangents = false;
7911                 break;
7912         }
7913
7914         if (r_shownormals.integer)
7915                 wanttangents = wantnormals = true;
7916
7917         // TODO: thread this
7918         // NOTE: R_PrepareRTLights() also caches entities
7919
7920         for (i = 0;i < r_refdef.scene.numentities;i++)
7921                 if (r_refdef.viewcache.entityvisible[i])
7922                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7923 }
7924
7925 //==================================================================================
7926
7927 static void R_View_UpdateEntityLighting (void)
7928 {
7929         int i;
7930         entity_render_t *ent;
7931         vec3_t tempdiffusenormal, avg;
7932         vec_t f, fa, fd, fdd;
7933         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7934
7935         for (i = 0;i < r_refdef.scene.numentities;i++)
7936         {
7937                 ent = r_refdef.scene.entities[i];
7938
7939                 // skip unseen models
7940                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7941                         continue;
7942
7943                 // skip bsp models
7944                 if (ent->model && ent->model->brush.num_leafs)
7945                 {
7946                         // TODO: use modellight for r_ambient settings on world?
7947                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7948                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7949                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7950                         continue;
7951                 }
7952
7953                 // fetch the lighting from the worldmodel data
7954                 VectorClear(ent->modellight_ambient);
7955                 VectorClear(ent->modellight_diffuse);
7956                 VectorClear(tempdiffusenormal);
7957                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7958                 {
7959                         vec3_t org;
7960                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7961                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7962                         if(ent->flags & RENDER_EQUALIZE)
7963                         {
7964                                 // first fix up ambient lighting...
7965                                 if(r_equalize_entities_minambient.value > 0)
7966                                 {
7967                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7968                                         if(fd > 0)
7969                                         {
7970                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7971                                                 if(fa < r_equalize_entities_minambient.value * fd)
7972                                                 {
7973                                                         // solve:
7974                                                         //   fa'/fd' = minambient
7975                                                         //   fa'+0.25*fd' = fa+0.25*fd
7976                                                         //   ...
7977                                                         //   fa' = fd' * minambient
7978                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7979                                                         //   ...
7980                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7981                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7982                                                         //   ...
7983                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7984                                                         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
7985                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7986                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7987                                                 }
7988                                         }
7989                                 }
7990
7991                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7992                                 {
7993                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7994                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7995                                         if(f > 0)
7996                                         {
7997                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7998                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7999                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8000                                         }
8001                                 }
8002                         }
8003                 }
8004                 else // highly rare
8005                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8006
8007                 // move the light direction into modelspace coordinates for lighting code
8008                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8009                 if(VectorLength2(ent->modellight_lightdir) == 0)
8010                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8011                 VectorNormalize(ent->modellight_lightdir);
8012         }
8013 }
8014
8015 #define MAX_LINEOFSIGHTTRACES 64
8016
8017 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8018 {
8019         int i;
8020         vec3_t boxmins, boxmaxs;
8021         vec3_t start;
8022         vec3_t end;
8023         dp_model_t *model = r_refdef.scene.worldmodel;
8024
8025         if (!model || !model->brush.TraceLineOfSight)
8026                 return true;
8027
8028         // expand the box a little
8029         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8030         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8031         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8032         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8033         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8034         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8035
8036         // return true if eye is inside enlarged box
8037         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8038                 return true;
8039
8040         // try center
8041         VectorCopy(eye, start);
8042         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8043         if (model->brush.TraceLineOfSight(model, start, end))
8044                 return true;
8045
8046         // try various random positions
8047         for (i = 0;i < numsamples;i++)
8048         {
8049                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8050                 if (model->brush.TraceLineOfSight(model, start, end))
8051                         return true;
8052         }
8053
8054         return false;
8055 }
8056
8057
8058 static void R_View_UpdateEntityVisible (void)
8059 {
8060         int i;
8061         int renderimask;
8062         int samples;
8063         entity_render_t *ent;
8064
8065         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8066                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8067                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8068                 :                                                          RENDER_EXTERIORMODEL;
8069         if (!r_drawviewmodel.integer)
8070                 renderimask |= RENDER_VIEWMODEL;
8071         if (!r_drawexteriormodel.integer)
8072                 renderimask |= RENDER_EXTERIORMODEL;
8073         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8074         {
8075                 // worldmodel can check visibility
8076                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8077                 for (i = 0;i < r_refdef.scene.numentities;i++)
8078                 {
8079                         ent = r_refdef.scene.entities[i];
8080                         if (!(ent->flags & renderimask))
8081                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
8082                         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))
8083                                 r_refdef.viewcache.entityvisible[i] = true;
8084                 }
8085                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8086                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8087                 {
8088                         for (i = 0;i < r_refdef.scene.numentities;i++)
8089                         {
8090                                 ent = r_refdef.scene.entities[i];
8091                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8092                                 {
8093                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8094                                         if (samples < 0)
8095                                                 continue; // temp entities do pvs only
8096                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8097                                                 ent->last_trace_visibility = realtime;
8098                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8099                                                 r_refdef.viewcache.entityvisible[i] = 0;
8100                                 }
8101                         }
8102                 }
8103         }
8104         else
8105         {
8106                 // no worldmodel or it can't check visibility
8107                 for (i = 0;i < r_refdef.scene.numentities;i++)
8108                 {
8109                         ent = r_refdef.scene.entities[i];
8110                         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));
8111                 }
8112         }
8113 }
8114
8115 /// only used if skyrendermasked, and normally returns false
8116 int R_DrawBrushModelsSky (void)
8117 {
8118         int i, sky;
8119         entity_render_t *ent;
8120
8121         sky = false;
8122         for (i = 0;i < r_refdef.scene.numentities;i++)
8123         {
8124                 if (!r_refdef.viewcache.entityvisible[i])
8125                         continue;
8126                 ent = r_refdef.scene.entities[i];
8127                 if (!ent->model || !ent->model->DrawSky)
8128                         continue;
8129                 ent->model->DrawSky(ent);
8130                 sky = true;
8131         }
8132         return sky;
8133 }
8134
8135 static void R_DrawNoModel(entity_render_t *ent);
8136 static void R_DrawModels(void)
8137 {
8138         int i;
8139         entity_render_t *ent;
8140
8141         for (i = 0;i < r_refdef.scene.numentities;i++)
8142         {
8143                 if (!r_refdef.viewcache.entityvisible[i])
8144                         continue;
8145                 ent = r_refdef.scene.entities[i];
8146                 r_refdef.stats.entities++;
8147                 if (ent->model && ent->model->Draw != NULL)
8148                         ent->model->Draw(ent);
8149                 else
8150                         R_DrawNoModel(ent);
8151         }
8152 }
8153
8154 static void R_DrawModelsDepth(void)
8155 {
8156         int i;
8157         entity_render_t *ent;
8158
8159         for (i = 0;i < r_refdef.scene.numentities;i++)
8160         {
8161                 if (!r_refdef.viewcache.entityvisible[i])
8162                         continue;
8163                 ent = r_refdef.scene.entities[i];
8164                 if (ent->model && ent->model->DrawDepth != NULL)
8165                         ent->model->DrawDepth(ent);
8166         }
8167 }
8168
8169 static void R_DrawModelsDebug(void)
8170 {
8171         int i;
8172         entity_render_t *ent;
8173
8174         for (i = 0;i < r_refdef.scene.numentities;i++)
8175         {
8176                 if (!r_refdef.viewcache.entityvisible[i])
8177                         continue;
8178                 ent = r_refdef.scene.entities[i];
8179                 if (ent->model && ent->model->DrawDebug != NULL)
8180                         ent->model->DrawDebug(ent);
8181         }
8182 }
8183
8184 static void R_DrawModelsAddWaterPlanes(void)
8185 {
8186         int i;
8187         entity_render_t *ent;
8188
8189         for (i = 0;i < r_refdef.scene.numentities;i++)
8190         {
8191                 if (!r_refdef.viewcache.entityvisible[i])
8192                         continue;
8193                 ent = r_refdef.scene.entities[i];
8194                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8195                         ent->model->DrawAddWaterPlanes(ent);
8196         }
8197 }
8198
8199 static void R_View_SetFrustum(void)
8200 {
8201         int i;
8202         double slopex, slopey;
8203         vec3_t forward, left, up, origin;
8204
8205         // we can't trust r_refdef.view.forward and friends in reflected scenes
8206         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8207
8208 #if 0
8209         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8210         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8211         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8212         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8213         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8214         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8215         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8216         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8217         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8218         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8219         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8220         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8221 #endif
8222
8223 #if 0
8224         zNear = r_refdef.nearclip;
8225         nudge = 1.0 - 1.0 / (1<<23);
8226         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8227         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8228         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8229         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8230         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8231         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8232         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8233         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8234 #endif
8235
8236
8237
8238 #if 0
8239         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8240         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8241         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8242         r_refdef.view.frustum[0].dist = m[15] - m[12];
8243
8244         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8245         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8246         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8247         r_refdef.view.frustum[1].dist = m[15] + m[12];
8248
8249         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8250         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8251         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8252         r_refdef.view.frustum[2].dist = m[15] - m[13];
8253
8254         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8255         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8256         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8257         r_refdef.view.frustum[3].dist = m[15] + m[13];
8258
8259         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8260         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8261         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8262         r_refdef.view.frustum[4].dist = m[15] - m[14];
8263
8264         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8265         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8266         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8267         r_refdef.view.frustum[5].dist = m[15] + m[14];
8268 #endif
8269
8270         if (r_refdef.view.useperspective)
8271         {
8272                 slopex = 1.0 / r_refdef.view.frustum_x;
8273                 slopey = 1.0 / r_refdef.view.frustum_y;
8274                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8275                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8276                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8277                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8278                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8279
8280                 // Leaving those out was a mistake, those were in the old code, and they
8281                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8282                 // I couldn't reproduce it after adding those normalizations. --blub
8283                 VectorNormalize(r_refdef.view.frustum[0].normal);
8284                 VectorNormalize(r_refdef.view.frustum[1].normal);
8285                 VectorNormalize(r_refdef.view.frustum[2].normal);
8286                 VectorNormalize(r_refdef.view.frustum[3].normal);
8287
8288                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8289                 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]);
8290                 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]);
8291                 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]);
8292                 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]);
8293
8294                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8295                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8296                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8297                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8298                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8299         }
8300         else
8301         {
8302                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8303                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8304                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8305                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8306                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8307                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8308                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8309                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8310                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8311                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8312         }
8313         r_refdef.view.numfrustumplanes = 5;
8314
8315         if (r_refdef.view.useclipplane)
8316         {
8317                 r_refdef.view.numfrustumplanes = 6;
8318                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8319         }
8320
8321         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8322                 PlaneClassify(r_refdef.view.frustum + i);
8323
8324         // LordHavoc: note to all quake engine coders, Quake had a special case
8325         // for 90 degrees which assumed a square view (wrong), so I removed it,
8326         // Quake2 has it disabled as well.
8327
8328         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8329         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8330         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8331         //PlaneClassify(&frustum[0]);
8332
8333         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8334         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8335         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8336         //PlaneClassify(&frustum[1]);
8337
8338         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8339         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8340         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8341         //PlaneClassify(&frustum[2]);
8342
8343         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8344         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8345         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8346         //PlaneClassify(&frustum[3]);
8347
8348         // nearclip plane
8349         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8350         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8351         //PlaneClassify(&frustum[4]);
8352 }
8353
8354 void R_View_Update(void)
8355 {
8356         R_Main_ResizeViewCache();
8357         R_View_SetFrustum();
8358         R_View_WorldVisibility(r_refdef.view.useclipplane);
8359         R_View_UpdateEntityVisible();
8360         R_View_UpdateEntityLighting();
8361 }
8362
8363 void R_SetupView(qboolean allowwaterclippingplane)
8364 {
8365         const float *customclipplane = NULL;
8366         float plane[4];
8367         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8368         {
8369                 // LordHavoc: couldn't figure out how to make this approach the
8370                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8371                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8372                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8373                         dist = r_refdef.view.clipplane.dist;
8374                 plane[0] = r_refdef.view.clipplane.normal[0];
8375                 plane[1] = r_refdef.view.clipplane.normal[1];
8376                 plane[2] = r_refdef.view.clipplane.normal[2];
8377                 plane[3] = dist;
8378                 customclipplane = plane;
8379         }
8380
8381         if (!r_refdef.view.useperspective)
8382                 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);
8383         else if (vid.stencil && r_useinfinitefarclip.integer)
8384                 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);
8385         else
8386                 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);
8387         R_SetViewport(&r_refdef.view.viewport);
8388 }
8389
8390 void R_EntityMatrix(const matrix4x4_t *matrix)
8391 {
8392         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8393         {
8394                 gl_modelmatrixchanged = false;
8395                 gl_modelmatrix = *matrix;
8396                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8397                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8398                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8399                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8400                 CHECKGLERROR
8401                 switch(vid.renderpath)
8402                 {
8403                 case RENDERPATH_D3D9:
8404 #ifdef SUPPORTD3D
8405                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8406                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8407 #endif
8408                         break;
8409                 case RENDERPATH_D3D10:
8410                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8411                         break;
8412                 case RENDERPATH_D3D11:
8413                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8414                         break;
8415                 case RENDERPATH_GL20:
8416                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8417                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8418                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8419                         break;
8420                 case RENDERPATH_CGGL:
8421 #ifdef SUPPORTCG
8422                         CHECKCGERROR
8423                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8424                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8425                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8426 #endif
8427                         break;
8428                 case RENDERPATH_GL13:
8429                 case RENDERPATH_GL11:
8430                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8431                         break;
8432                 }
8433         }
8434 }
8435
8436 void R_ResetViewRendering2D(void)
8437 {
8438         r_viewport_t viewport;
8439         DrawQ_Finish();
8440
8441         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8442         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);
8443         R_SetViewport(&viewport);
8444         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8445         GL_Color(1, 1, 1, 1);
8446         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8447         GL_BlendFunc(GL_ONE, GL_ZERO);
8448         GL_AlphaTest(false);
8449         GL_ScissorTest(false);
8450         GL_DepthMask(false);
8451         GL_DepthRange(0, 1);
8452         GL_DepthTest(false);
8453         GL_DepthFunc(GL_LEQUAL);
8454         R_EntityMatrix(&identitymatrix);
8455         R_Mesh_ResetTextureState();
8456         GL_PolygonOffset(0, 0);
8457         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8458         switch(vid.renderpath)
8459         {
8460         case RENDERPATH_GL11:
8461         case RENDERPATH_GL13:
8462         case RENDERPATH_GL20:
8463         case RENDERPATH_CGGL:
8464                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8465                 break;
8466         case RENDERPATH_D3D9:
8467         case RENDERPATH_D3D10:
8468         case RENDERPATH_D3D11:
8469                 break;
8470         }
8471         GL_CullFace(GL_NONE);
8472 }
8473
8474 void R_ResetViewRendering3D(void)
8475 {
8476         DrawQ_Finish();
8477
8478         R_SetupView(true);
8479         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8480         GL_Color(1, 1, 1, 1);
8481         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8482         GL_BlendFunc(GL_ONE, GL_ZERO);
8483         GL_AlphaTest(false);
8484         GL_ScissorTest(true);
8485         GL_DepthMask(true);
8486         GL_DepthRange(0, 1);
8487         GL_DepthTest(true);
8488         GL_DepthFunc(GL_LEQUAL);
8489         R_EntityMatrix(&identitymatrix);
8490         R_Mesh_ResetTextureState();
8491         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8492         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8493         switch(vid.renderpath)
8494         {
8495         case RENDERPATH_GL11:
8496         case RENDERPATH_GL13:
8497         case RENDERPATH_GL20:
8498         case RENDERPATH_CGGL:
8499                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8500                 break;
8501         case RENDERPATH_D3D9:
8502         case RENDERPATH_D3D10:
8503         case RENDERPATH_D3D11:
8504                 break;
8505         }
8506         GL_CullFace(r_refdef.view.cullface_back);
8507 }
8508
8509 /*
8510 ================
8511 R_RenderView_UpdateViewVectors
8512 ================
8513 */
8514 static void R_RenderView_UpdateViewVectors(void)
8515 {
8516         // break apart the view matrix into vectors for various purposes
8517         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8518         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8519         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8520         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8521         // make an inverted copy of the view matrix for tracking sprites
8522         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8523 }
8524
8525 void R_RenderScene(void);
8526 void R_RenderWaterPlanes(void);
8527
8528 static void R_Water_StartFrame(void)
8529 {
8530         int i;
8531         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8532         r_waterstate_waterplane_t *p;
8533
8534         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8535                 return;
8536
8537         switch(vid.renderpath)
8538         {
8539         case RENDERPATH_GL20:
8540         case RENDERPATH_CGGL:
8541         case RENDERPATH_D3D9:
8542         case RENDERPATH_D3D10:
8543         case RENDERPATH_D3D11:
8544                 break;
8545         case RENDERPATH_GL13:
8546         case RENDERPATH_GL11:
8547                 return;
8548         }
8549
8550         // set waterwidth and waterheight to the water resolution that will be
8551         // used (often less than the screen resolution for faster rendering)
8552         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8553         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8554
8555         // calculate desired texture sizes
8556         // can't use water if the card does not support the texture size
8557         if (!r_water.integer || r_showsurfaces.integer)
8558                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8559         else if (vid.support.arb_texture_non_power_of_two)
8560         {
8561                 texturewidth = waterwidth;
8562                 textureheight = waterheight;
8563                 camerawidth = waterwidth;
8564                 cameraheight = waterheight;
8565         }
8566         else
8567         {
8568                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8569                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8570                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8571                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8572         }
8573
8574         // allocate textures as needed
8575         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8576         {
8577                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8578                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8579                 {
8580                         if (p->texture_refraction)
8581                                 R_FreeTexture(p->texture_refraction);
8582                         p->texture_refraction = NULL;
8583                         if (p->texture_reflection)
8584                                 R_FreeTexture(p->texture_reflection);
8585                         p->texture_reflection = NULL;
8586                         if (p->texture_camera)
8587                                 R_FreeTexture(p->texture_camera);
8588                         p->texture_camera = NULL;
8589                 }
8590                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8591                 r_waterstate.texturewidth = texturewidth;
8592                 r_waterstate.textureheight = textureheight;
8593                 r_waterstate.camerawidth = camerawidth;
8594                 r_waterstate.cameraheight = cameraheight;
8595         }
8596
8597         if (r_waterstate.texturewidth)
8598         {
8599                 r_waterstate.enabled = true;
8600
8601                 // when doing a reduced render (HDR) we want to use a smaller area
8602                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8603                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8604
8605                 // set up variables that will be used in shader setup
8606                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8607                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8608                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8609                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8610         }
8611
8612         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8613         r_waterstate.numwaterplanes = 0;
8614 }
8615
8616 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8617 {
8618         int triangleindex, planeindex;
8619         const int *e;
8620         vec3_t vert[3];
8621         vec3_t normal;
8622         vec3_t center;
8623         mplane_t plane;
8624         int cam_ent;
8625         r_waterstate_waterplane_t *p;
8626         texture_t *t = R_GetCurrentTexture(surface->texture);
8627         cam_ent = t->camera_entity;
8628         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8629                 cam_ent = 0;
8630
8631         // just use the first triangle with a valid normal for any decisions
8632         VectorClear(normal);
8633         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8634         {
8635                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8636                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8637                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8638                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8639                 if (VectorLength2(normal) >= 0.001)
8640                         break;
8641         }
8642
8643         VectorCopy(normal, plane.normal);
8644         VectorNormalize(plane.normal);
8645         plane.dist = DotProduct(vert[0], plane.normal);
8646         PlaneClassify(&plane);
8647         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8648         {
8649                 // skip backfaces (except if nocullface is set)
8650                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8651                         return;
8652                 VectorNegate(plane.normal, plane.normal);
8653                 plane.dist *= -1;
8654                 PlaneClassify(&plane);
8655         }
8656
8657
8658         // find a matching plane if there is one
8659         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8660                 if(p->camera_entity == t->camera_entity)
8661                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8662                                 break;
8663         if (planeindex >= r_waterstate.maxwaterplanes)
8664                 return; // nothing we can do, out of planes
8665
8666         // if this triangle does not fit any known plane rendered this frame, add one
8667         if (planeindex >= r_waterstate.numwaterplanes)
8668         {
8669                 // store the new plane
8670                 r_waterstate.numwaterplanes++;
8671                 p->plane = plane;
8672                 // clear materialflags and pvs
8673                 p->materialflags = 0;
8674                 p->pvsvalid = false;
8675                 p->camera_entity = t->camera_entity;
8676         }
8677         // merge this surface's materialflags into the waterplane
8678         p->materialflags |= t->currentmaterialflags;
8679         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8680         {
8681                 // merge this surface's PVS into the waterplane
8682                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8683                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8684                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8685                 {
8686                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8687                         p->pvsvalid = true;
8688                 }
8689         }
8690 }
8691
8692 static void R_Water_ProcessPlanes(void)
8693 {
8694         r_refdef_view_t originalview;
8695         r_refdef_view_t myview;
8696         int planeindex;
8697         r_waterstate_waterplane_t *p;
8698         vec3_t visorigin;
8699
8700         originalview = r_refdef.view;
8701
8702         // make sure enough textures are allocated
8703         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8704         {
8705                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8706                 {
8707                         if (!p->texture_refraction)
8708                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8709                         if (!p->texture_refraction)
8710                                 goto error;
8711                 }
8712                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8713                 {
8714                         if (!p->texture_camera)
8715                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
8716                         if (!p->texture_camera)
8717                                 goto error;
8718                 }
8719
8720                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8721                 {
8722                         if (!p->texture_reflection)
8723                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8724                         if (!p->texture_reflection)
8725                                 goto error;
8726                 }
8727         }
8728
8729         // render views
8730         r_refdef.view = originalview;
8731         r_refdef.view.showdebug = false;
8732         r_refdef.view.width = r_waterstate.waterwidth;
8733         r_refdef.view.height = r_waterstate.waterheight;
8734         r_refdef.view.useclipplane = true;
8735         myview = r_refdef.view;
8736         r_waterstate.renderingscene = true;
8737         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8738         {
8739                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8740                 {
8741                         r_refdef.view = myview;
8742                         // render reflected scene and copy into texture
8743                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8744                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8745                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8746                         r_refdef.view.clipplane = p->plane;
8747                         // reverse the cullface settings for this render
8748                         r_refdef.view.cullface_front = GL_FRONT;
8749                         r_refdef.view.cullface_back = GL_BACK;
8750                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8751                         {
8752                                 r_refdef.view.usecustompvs = true;
8753                                 if (p->pvsvalid)
8754                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8755                                 else
8756                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8757                         }
8758
8759                         R_ResetViewRendering3D();
8760                         R_ClearScreen(r_refdef.fogenabled);
8761                         R_View_Update();
8762                         R_RenderScene();
8763
8764                         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);
8765                 }
8766
8767                 // render the normal view scene and copy into texture
8768                 // (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)
8769                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8770                 {
8771                         r_waterstate.renderingrefraction = true;
8772                         r_refdef.view = myview;
8773
8774                         r_refdef.view.clipplane = p->plane;
8775                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8776                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8777
8778                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8779                         {
8780                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8781                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8782                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8783                                 R_RenderView_UpdateViewVectors();
8784                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8785                                 {
8786                                         r_refdef.view.usecustompvs = true;
8787                                         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);
8788                                 }
8789                         }
8790
8791                         PlaneClassify(&r_refdef.view.clipplane);
8792
8793                         R_ResetViewRendering3D();
8794                         R_ClearScreen(r_refdef.fogenabled);
8795                         R_View_Update();
8796                         R_RenderScene();
8797
8798                         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);
8799                         r_waterstate.renderingrefraction = false;
8800                 }
8801                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8802                 {
8803                         r_refdef.view = myview;
8804
8805                         r_refdef.view.clipplane = p->plane;
8806                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8807                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8808
8809                         r_refdef.view.width = r_waterstate.camerawidth;
8810                         r_refdef.view.height = r_waterstate.cameraheight;
8811                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8812                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8813
8814                         if(p->camera_entity)
8815                         {
8816                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8817                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8818                         }
8819
8820                         // reverse the cullface settings for this render
8821                         r_refdef.view.cullface_front = GL_FRONT;
8822                         r_refdef.view.cullface_back = GL_BACK;
8823                         // also reverse the view matrix
8824                         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
8825                         R_RenderView_UpdateViewVectors();
8826                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8827                         {
8828                                 r_refdef.view.usecustompvs = true;
8829                                 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);
8830                         }
8831                         
8832                         // camera needs no clipplane
8833                         r_refdef.view.useclipplane = false;
8834
8835                         PlaneClassify(&r_refdef.view.clipplane);
8836
8837                         R_ResetViewRendering3D();
8838                         R_ClearScreen(r_refdef.fogenabled);
8839                         R_View_Update();
8840                         R_RenderScene();
8841
8842                         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);
8843                         r_waterstate.renderingrefraction = false;
8844                 }
8845
8846         }
8847         r_waterstate.renderingscene = false;
8848         r_refdef.view = originalview;
8849         R_ResetViewRendering3D();
8850         R_ClearScreen(r_refdef.fogenabled);
8851         R_View_Update();
8852         return;
8853 error:
8854         r_refdef.view = originalview;
8855         r_waterstate.renderingscene = false;
8856         Cvar_SetValueQuick(&r_water, 0);
8857         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8858         return;
8859 }
8860
8861 void R_Bloom_StartFrame(void)
8862 {
8863         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8864
8865         switch(vid.renderpath)
8866         {
8867         case RENDERPATH_GL20:
8868         case RENDERPATH_CGGL:
8869         case RENDERPATH_D3D9:
8870         case RENDERPATH_D3D10:
8871         case RENDERPATH_D3D11:
8872                 break;
8873         case RENDERPATH_GL13:
8874         case RENDERPATH_GL11:
8875                 return;
8876         }
8877
8878         // set bloomwidth and bloomheight to the bloom resolution that will be
8879         // used (often less than the screen resolution for faster rendering)
8880         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8881         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8882         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8883         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8884         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8885
8886         // calculate desired texture sizes
8887         if (vid.support.arb_texture_non_power_of_two)
8888         {
8889                 screentexturewidth = r_refdef.view.width;
8890                 screentextureheight = r_refdef.view.height;
8891                 bloomtexturewidth = r_bloomstate.bloomwidth;
8892                 bloomtextureheight = r_bloomstate.bloomheight;
8893         }
8894         else
8895         {
8896                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8897                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8898                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8899                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8900         }
8901
8902         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))
8903         {
8904                 Cvar_SetValueQuick(&r_hdr, 0);
8905                 Cvar_SetValueQuick(&r_bloom, 0);
8906                 Cvar_SetValueQuick(&r_motionblur, 0);
8907                 Cvar_SetValueQuick(&r_damageblur, 0);
8908         }
8909
8910         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)))
8911                 screentexturewidth = screentextureheight = 0;
8912         if (!r_hdr.integer && !r_bloom.integer)
8913                 bloomtexturewidth = bloomtextureheight = 0;
8914
8915         // allocate textures as needed
8916         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8917         {
8918                 if (r_bloomstate.texture_screen)
8919                         R_FreeTexture(r_bloomstate.texture_screen);
8920                 r_bloomstate.texture_screen = NULL;
8921                 r_bloomstate.screentexturewidth = screentexturewidth;
8922                 r_bloomstate.screentextureheight = screentextureheight;
8923                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8924                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
8925         }
8926         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8927         {
8928                 if (r_bloomstate.texture_bloom)
8929                         R_FreeTexture(r_bloomstate.texture_bloom);
8930                 r_bloomstate.texture_bloom = NULL;
8931                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8932                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8933                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8934                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
8935         }
8936
8937         // when doing a reduced render (HDR) we want to use a smaller area
8938         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8939         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8940         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8941         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8942         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8943
8944         // set up a texcoord array for the full resolution screen image
8945         // (we have to keep this around to copy back during final render)
8946         r_bloomstate.screentexcoord2f[0] = 0;
8947         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8948         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8949         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8950         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8951         r_bloomstate.screentexcoord2f[5] = 0;
8952         r_bloomstate.screentexcoord2f[6] = 0;
8953         r_bloomstate.screentexcoord2f[7] = 0;
8954
8955         // set up a texcoord array for the reduced resolution bloom image
8956         // (which will be additive blended over the screen image)
8957         r_bloomstate.bloomtexcoord2f[0] = 0;
8958         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8959         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8960         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8961         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8962         r_bloomstate.bloomtexcoord2f[5] = 0;
8963         r_bloomstate.bloomtexcoord2f[6] = 0;
8964         r_bloomstate.bloomtexcoord2f[7] = 0;
8965
8966         switch(vid.renderpath)
8967         {
8968         case RENDERPATH_GL11:
8969         case RENDERPATH_GL13:
8970         case RENDERPATH_GL20:
8971         case RENDERPATH_CGGL:
8972                 break;
8973         case RENDERPATH_D3D9:
8974         case RENDERPATH_D3D10:
8975         case RENDERPATH_D3D11:
8976                 {
8977                         int i;
8978                         for (i = 0;i < 4;i++)
8979                         {
8980                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8981                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8982                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8983                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8984                         }
8985                 }
8986                 break;
8987         }
8988
8989         if (r_hdr.integer || r_bloom.integer)
8990         {
8991                 r_bloomstate.enabled = true;
8992                 r_bloomstate.hdr = r_hdr.integer != 0;
8993         }
8994
8995         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);
8996 }
8997
8998 void R_Bloom_CopyBloomTexture(float colorscale)
8999 {
9000         r_refdef.stats.bloom++;
9001
9002         // scale down screen texture to the bloom texture size
9003         CHECKGLERROR
9004         R_SetViewport(&r_bloomstate.viewport);
9005         GL_BlendFunc(GL_ONE, GL_ZERO);
9006         GL_Color(colorscale, colorscale, colorscale, 1);
9007         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9008         switch(vid.renderpath)
9009         {
9010         case RENDERPATH_GL11:
9011         case RENDERPATH_GL13:
9012         case RENDERPATH_GL20:
9013         case RENDERPATH_CGGL:
9014                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9015                 break;
9016         case RENDERPATH_D3D9:
9017         case RENDERPATH_D3D10:
9018         case RENDERPATH_D3D11:
9019                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9020                 break;
9021         }
9022         // TODO: do boxfilter scale-down in shader?
9023         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9024         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9025         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9026
9027         // we now have a bloom image in the framebuffer
9028         // copy it into the bloom image texture for later processing
9029         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);
9030         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9031 }
9032
9033 void R_Bloom_CopyHDRTexture(void)
9034 {
9035         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);
9036         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9037 }
9038
9039 void R_Bloom_MakeTexture(void)
9040 {
9041         int x, range, dir;
9042         float xoffset, yoffset, r, brighten;
9043
9044         r_refdef.stats.bloom++;
9045
9046         R_ResetViewRendering2D();
9047
9048         // we have a bloom image in the framebuffer
9049         CHECKGLERROR
9050         R_SetViewport(&r_bloomstate.viewport);
9051
9052         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9053         {
9054                 x *= 2;
9055                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9056                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9057                 GL_Color(r,r,r,1);
9058                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9059                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9060                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9061                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9062
9063                 // copy the vertically blurred bloom view to a texture
9064                 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);
9065                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9066         }
9067
9068         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9069         brighten = r_bloom_brighten.value;
9070         if (r_hdr.integer)
9071                 brighten *= r_hdr_range.value;
9072         brighten = sqrt(brighten);
9073         if(range >= 1)
9074                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9075         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9076
9077         for (dir = 0;dir < 2;dir++)
9078         {
9079                 // blend on at multiple vertical offsets to achieve a vertical blur
9080                 // TODO: do offset blends using GLSL
9081                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9082                 GL_BlendFunc(GL_ONE, GL_ZERO);
9083                 for (x = -range;x <= range;x++)
9084                 {
9085                         if (!dir){xoffset = 0;yoffset = x;}
9086                         else {xoffset = x;yoffset = 0;}
9087                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9088                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9089                         // compute a texcoord array with the specified x and y offset
9090                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9091                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9092                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9093                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9094                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9095                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9096                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9097                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9098                         // this r value looks like a 'dot' particle, fading sharply to
9099                         // black at the edges
9100                         // (probably not realistic but looks good enough)
9101                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9102                         //r = brighten/(range*2+1);
9103                         r = brighten / (range * 2 + 1);
9104                         if(range >= 1)
9105                                 r *= (1 - x*x/(float)(range*range));
9106                         GL_Color(r, r, r, 1);
9107                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9108                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9109                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9110                         GL_BlendFunc(GL_ONE, GL_ONE);
9111                 }
9112
9113                 // copy the vertically blurred bloom view to a texture
9114                 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);
9115                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9116         }
9117 }
9118
9119 void R_HDR_RenderBloomTexture(void)
9120 {
9121         int oldwidth, oldheight;
9122         float oldcolorscale;
9123
9124         oldcolorscale = r_refdef.view.colorscale;
9125         oldwidth = r_refdef.view.width;
9126         oldheight = r_refdef.view.height;
9127         r_refdef.view.width = r_bloomstate.bloomwidth;
9128         r_refdef.view.height = r_bloomstate.bloomheight;
9129
9130         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9131         // TODO: add exposure compensation features
9132         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9133
9134         r_refdef.view.showdebug = false;
9135         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9136
9137         R_ResetViewRendering3D();
9138
9139         R_ClearScreen(r_refdef.fogenabled);
9140         if (r_timereport_active)
9141                 R_TimeReport("HDRclear");
9142
9143         R_View_Update();
9144         if (r_timereport_active)
9145                 R_TimeReport("visibility");
9146
9147         // only do secondary renders with HDR if r_hdr is 2 or higher
9148         r_waterstate.numwaterplanes = 0;
9149         if (r_waterstate.enabled && r_hdr.integer >= 2)
9150                 R_RenderWaterPlanes();
9151
9152         r_refdef.view.showdebug = true;
9153         R_RenderScene();
9154         r_waterstate.numwaterplanes = 0;
9155
9156         R_ResetViewRendering2D();
9157
9158         R_Bloom_CopyHDRTexture();
9159         R_Bloom_MakeTexture();
9160
9161         // restore the view settings
9162         r_refdef.view.width = oldwidth;
9163         r_refdef.view.height = oldheight;
9164         r_refdef.view.colorscale = oldcolorscale;
9165
9166         R_ResetViewRendering3D();
9167
9168         R_ClearScreen(r_refdef.fogenabled);
9169         if (r_timereport_active)
9170                 R_TimeReport("viewclear");
9171 }
9172
9173 static void R_BlendView(void)
9174 {
9175         unsigned int permutation;
9176         float uservecs[4][4];
9177
9178         switch (vid.renderpath)
9179         {
9180         case RENDERPATH_GL20:
9181         case RENDERPATH_CGGL:
9182         case RENDERPATH_D3D9:
9183         case RENDERPATH_D3D10:
9184         case RENDERPATH_D3D11:
9185                 permutation =
9186                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9187                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9188                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9189                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9190                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9191
9192                 if (r_bloomstate.texture_screen)
9193                 {
9194                         // make sure the buffer is available
9195                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9196
9197                         R_ResetViewRendering2D();
9198
9199                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9200                         {
9201                                 // declare variables
9202                                 float speed;
9203                                 static float avgspeed;
9204
9205                                 speed = VectorLength(cl.movement_velocity);
9206
9207                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9208                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9209
9210                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9211                                 speed = bound(0, speed, 1);
9212                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9213
9214                                 // calculate values into a standard alpha
9215                                 cl.motionbluralpha = 1 - exp(-
9216                                                 (
9217                                                  (r_motionblur.value * speed / 80)
9218                                                  +
9219                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9220                                                 )
9221                                                 /
9222                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9223                                            );
9224
9225                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9226                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9227                                 // apply the blur
9228                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9229                                 {
9230                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9231                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9232                                         switch(vid.renderpath)
9233                                         {
9234                                         case RENDERPATH_GL11:
9235                                         case RENDERPATH_GL13:
9236                                         case RENDERPATH_GL20:
9237                                         case RENDERPATH_CGGL:
9238                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9239                                                 break;
9240                                         case RENDERPATH_D3D9:
9241                                         case RENDERPATH_D3D10:
9242                                         case RENDERPATH_D3D11:
9243                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9244                                                 break;
9245                                         }
9246                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9247                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9248                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9249                                 }
9250                         }
9251
9252                         // copy view into the screen texture
9253                         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);
9254                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9255                 }
9256                 else if (!r_bloomstate.texture_bloom)
9257                 {
9258                         // we may still have to do view tint...
9259                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9260                         {
9261                                 // apply a color tint to the whole view
9262                                 R_ResetViewRendering2D();
9263                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9264                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9265                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9266                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9267                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9268                         }
9269                         break; // no screen processing, no bloom, skip it
9270                 }
9271
9272                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9273                 {
9274                         // render simple bloom effect
9275                         // copy the screen and shrink it and darken it for the bloom process
9276                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9277                         // make the bloom texture
9278                         R_Bloom_MakeTexture();
9279                 }
9280
9281 #if _MSC_VER >= 1400
9282 #define sscanf sscanf_s
9283 #endif
9284                 memset(uservecs, 0, sizeof(uservecs));
9285                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9286                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9287                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9288                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9289
9290                 R_ResetViewRendering2D();
9291                 GL_Color(1, 1, 1, 1);
9292                 GL_BlendFunc(GL_ONE, GL_ZERO);
9293
9294                 switch(vid.renderpath)
9295                 {
9296                 case RENDERPATH_GL20:
9297                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9298                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9299                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9300                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9301                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9302                         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]);
9303                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9304                         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]);
9305                         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]);
9306                         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]);
9307                         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]);
9308                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9309                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9310                         if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9311                         break;
9312                 case RENDERPATH_CGGL:
9313 #ifdef SUPPORTCG
9314                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9315                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9316                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9317                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9318                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9319                         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
9320                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9321                         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
9322                         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
9323                         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
9324                         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
9325                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9326                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9327                         if (r_cg_permutation->fp_BloomColorSubtract   ) cgGLSetParameter4f(r_cg_permutation->fp_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9328 #endif
9329                         break;
9330                 case RENDERPATH_D3D9:
9331 #ifdef SUPPORTD3D
9332                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
9333                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9334                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9335                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9336                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9337                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9338                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9339                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9340                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9341                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9342                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9343                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9344                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9345                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9346                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9347 #endif
9348                         break;
9349                 case RENDERPATH_D3D10:
9350                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9351                         break;
9352                 case RENDERPATH_D3D11:
9353                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9354                         break;
9355                 default:
9356                         break;
9357                 }
9358                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9359                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9360                 break;
9361         case RENDERPATH_GL13:
9362         case RENDERPATH_GL11:
9363                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9364                 {
9365                         // apply a color tint to the whole view
9366                         R_ResetViewRendering2D();
9367                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9368                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9369                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9370                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9371                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9372                 }
9373                 break;
9374         }
9375 }
9376
9377 matrix4x4_t r_waterscrollmatrix;
9378
9379 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9380 {
9381         if (r_refdef.fog_density)
9382         {
9383                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9384                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9385                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9386
9387                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9388                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9389                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9390                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9391
9392                 {
9393                         vec3_t fogvec;
9394                         VectorCopy(r_refdef.fogcolor, fogvec);
9395                         //   color.rgb *= ContrastBoost * SceneBrightness;
9396                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9397                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9398                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9399                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9400                 }
9401         }
9402 }
9403
9404 void R_UpdateVariables(void)
9405 {
9406         R_Textures_Frame();
9407
9408         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9409
9410         r_refdef.farclip = r_farclip_base.value;
9411         if (r_refdef.scene.worldmodel)
9412                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9413         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9414
9415         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9416                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9417         r_refdef.polygonfactor = 0;
9418         r_refdef.polygonoffset = 0;
9419         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9420         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9421
9422         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9423         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9424         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9425         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9426         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9427         if (r_showsurfaces.integer)
9428         {
9429                 r_refdef.scene.rtworld = false;
9430                 r_refdef.scene.rtworldshadows = false;
9431                 r_refdef.scene.rtdlight = false;
9432                 r_refdef.scene.rtdlightshadows = false;
9433                 r_refdef.lightmapintensity = 0;
9434         }
9435
9436         if (gamemode == GAME_NEHAHRA)
9437         {
9438                 if (gl_fogenable.integer)
9439                 {
9440                         r_refdef.oldgl_fogenable = true;
9441                         r_refdef.fog_density = gl_fogdensity.value;
9442                         r_refdef.fog_red = gl_fogred.value;
9443                         r_refdef.fog_green = gl_foggreen.value;
9444                         r_refdef.fog_blue = gl_fogblue.value;
9445                         r_refdef.fog_alpha = 1;
9446                         r_refdef.fog_start = 0;
9447                         r_refdef.fog_end = gl_skyclip.value;
9448                         r_refdef.fog_height = 1<<30;
9449                         r_refdef.fog_fadedepth = 128;
9450                 }
9451                 else if (r_refdef.oldgl_fogenable)
9452                 {
9453                         r_refdef.oldgl_fogenable = false;
9454                         r_refdef.fog_density = 0;
9455                         r_refdef.fog_red = 0;
9456                         r_refdef.fog_green = 0;
9457                         r_refdef.fog_blue = 0;
9458                         r_refdef.fog_alpha = 0;
9459                         r_refdef.fog_start = 0;
9460                         r_refdef.fog_end = 0;
9461                         r_refdef.fog_height = 1<<30;
9462                         r_refdef.fog_fadedepth = 128;
9463                 }
9464         }
9465
9466         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9467         r_refdef.fog_start = max(0, r_refdef.fog_start);
9468         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9469
9470         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9471
9472         if (r_refdef.fog_density && r_drawfog.integer)
9473         {
9474                 r_refdef.fogenabled = true;
9475                 // this is the point where the fog reaches 0.9986 alpha, which we
9476                 // consider a good enough cutoff point for the texture
9477                 // (0.9986 * 256 == 255.6)
9478                 if (r_fog_exp2.integer)
9479                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9480                 else
9481                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9482                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9483                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9484                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9485                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9486                         R_BuildFogHeightTexture();
9487                 // fog color was already set
9488                 // update the fog texture
9489                 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)
9490                         R_BuildFogTexture();
9491                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9492                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9493         }
9494         else
9495                 r_refdef.fogenabled = false;
9496
9497         switch(vid.renderpath)
9498         {
9499         case RENDERPATH_GL20:
9500         case RENDERPATH_CGGL:
9501         case RENDERPATH_D3D9:
9502         case RENDERPATH_D3D10:
9503         case RENDERPATH_D3D11:
9504                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9505                 {
9506                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9507                         {
9508                                 // build GLSL gamma texture
9509 #define RAMPWIDTH 256
9510                                 unsigned short ramp[RAMPWIDTH * 3];
9511                                 unsigned char rampbgr[RAMPWIDTH][4];
9512                                 int i;
9513
9514                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9515
9516                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9517                                 for(i = 0; i < RAMPWIDTH; ++i)
9518                                 {
9519                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9520                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9521                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9522                                         rampbgr[i][3] = 0;
9523                                 }
9524                                 if (r_texture_gammaramps)
9525                                 {
9526                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9527                                 }
9528                                 else
9529                                 {
9530                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9531                                 }
9532                         }
9533                 }
9534                 else
9535                 {
9536                         // remove GLSL gamma texture
9537                 }
9538                 break;
9539         case RENDERPATH_GL13:
9540         case RENDERPATH_GL11:
9541                 break;
9542         }
9543 }
9544
9545 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9546 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9547 /*
9548 ================
9549 R_SelectScene
9550 ================
9551 */
9552 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9553         if( scenetype != r_currentscenetype ) {
9554                 // store the old scenetype
9555                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9556                 r_currentscenetype = scenetype;
9557                 // move in the new scene
9558                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9559         }
9560 }
9561
9562 /*
9563 ================
9564 R_GetScenePointer
9565 ================
9566 */
9567 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9568 {
9569         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9570         if( scenetype == r_currentscenetype ) {
9571                 return &r_refdef.scene;
9572         } else {
9573                 return &r_scenes_store[ scenetype ];
9574         }
9575 }
9576
9577 /*
9578 ================
9579 R_RenderView
9580 ================
9581 */
9582 void R_RenderView(void)
9583 {
9584         if (r_timereport_active)
9585                 R_TimeReport("start");
9586         r_textureframe++; // used only by R_GetCurrentTexture
9587         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9588
9589         if (!r_drawentities.integer)
9590                 r_refdef.scene.numentities = 0;
9591
9592         R_AnimCache_ClearCache();
9593         R_FrameData_NewFrame();
9594
9595         if (r_refdef.view.isoverlay)
9596         {
9597                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9598                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9599                 R_TimeReport("depthclear");
9600
9601                 r_refdef.view.showdebug = false;
9602
9603                 r_waterstate.enabled = false;
9604                 r_waterstate.numwaterplanes = 0;
9605
9606                 R_RenderScene();
9607
9608                 CHECKGLERROR
9609                 return;
9610         }
9611
9612         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9613                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9614
9615         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9616
9617         R_RenderView_UpdateViewVectors();
9618
9619         R_Shadow_UpdateWorldLightSelection();
9620
9621         R_Bloom_StartFrame();
9622         R_Water_StartFrame();
9623
9624         CHECKGLERROR
9625         if (r_timereport_active)
9626                 R_TimeReport("viewsetup");
9627
9628         R_ResetViewRendering3D();
9629
9630         if (r_refdef.view.clear || r_refdef.fogenabled)
9631         {
9632                 R_ClearScreen(r_refdef.fogenabled);
9633                 if (r_timereport_active)
9634                         R_TimeReport("viewclear");
9635         }
9636         r_refdef.view.clear = true;
9637
9638         // this produces a bloom texture to be used in R_BlendView() later
9639         if (r_hdr.integer && r_bloomstate.bloomwidth)
9640         {
9641                 R_HDR_RenderBloomTexture();
9642                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9643                 r_textureframe++; // used only by R_GetCurrentTexture
9644         }
9645
9646         r_refdef.view.showdebug = true;
9647
9648         R_View_Update();
9649         if (r_timereport_active)
9650                 R_TimeReport("visibility");
9651
9652         r_waterstate.numwaterplanes = 0;
9653         if (r_waterstate.enabled)
9654                 R_RenderWaterPlanes();
9655
9656         R_RenderScene();
9657         r_waterstate.numwaterplanes = 0;
9658
9659         R_BlendView();
9660         if (r_timereport_active)
9661                 R_TimeReport("blendview");
9662
9663         GL_Scissor(0, 0, vid.width, vid.height);
9664         GL_ScissorTest(false);
9665         CHECKGLERROR
9666 }
9667
9668 void R_RenderWaterPlanes(void)
9669 {
9670         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9671         {
9672                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9673                 if (r_timereport_active)
9674                         R_TimeReport("waterworld");
9675         }
9676
9677         // don't let sound skip if going slow
9678         if (r_refdef.scene.extraupdate)
9679                 S_ExtraUpdate ();
9680
9681         R_DrawModelsAddWaterPlanes();
9682         if (r_timereport_active)
9683                 R_TimeReport("watermodels");
9684
9685         if (r_waterstate.numwaterplanes)
9686         {
9687                 R_Water_ProcessPlanes();
9688                 if (r_timereport_active)
9689                         R_TimeReport("waterscenes");
9690         }
9691 }
9692
9693 extern void R_DrawLightningBeams (void);
9694 extern void VM_CL_AddPolygonsToMeshQueue (void);
9695 extern void R_DrawPortals (void);
9696 extern cvar_t cl_locs_show;
9697 static void R_DrawLocs(void);
9698 static void R_DrawEntityBBoxes(void);
9699 static void R_DrawModelDecals(void);
9700 extern void R_DrawModelShadows(void);
9701 extern void R_DrawModelShadowMaps(void);
9702 extern cvar_t cl_decals_newsystem;
9703 extern qboolean r_shadow_usingdeferredprepass;
9704 void R_RenderScene(void)
9705 {
9706         qboolean shadowmapping = false;
9707
9708         if (r_timereport_active)
9709                 R_TimeReport("beginscene");
9710
9711         r_refdef.stats.renders++;
9712
9713         R_UpdateFogColor();
9714
9715         // don't let sound skip if going slow
9716         if (r_refdef.scene.extraupdate)
9717                 S_ExtraUpdate ();
9718
9719         R_MeshQueue_BeginScene();
9720
9721         R_SkyStartFrame();
9722
9723         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);
9724
9725         if (r_timereport_active)
9726                 R_TimeReport("skystartframe");
9727
9728         if (cl.csqc_vidvars.drawworld)
9729         {
9730                 // don't let sound skip if going slow
9731                 if (r_refdef.scene.extraupdate)
9732                         S_ExtraUpdate ();
9733
9734                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9735                 {
9736                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9737                         if (r_timereport_active)
9738                                 R_TimeReport("worldsky");
9739                 }
9740
9741                 if (R_DrawBrushModelsSky() && r_timereport_active)
9742                         R_TimeReport("bmodelsky");
9743
9744                 if (skyrendermasked && skyrenderlater)
9745                 {
9746                         // we have to force off the water clipping plane while rendering sky
9747                         R_SetupView(false);
9748                         R_Sky();
9749                         R_SetupView(true);
9750                         if (r_timereport_active)
9751                                 R_TimeReport("sky");
9752                 }
9753         }
9754
9755         R_AnimCache_CacheVisibleEntities();
9756         if (r_timereport_active)
9757                 R_TimeReport("animation");
9758
9759         R_Shadow_PrepareLights();
9760         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9761                 R_Shadow_PrepareModelShadows();
9762         if (r_timereport_active)
9763                 R_TimeReport("preparelights");
9764
9765         if (R_Shadow_ShadowMappingEnabled())
9766                 shadowmapping = true;
9767
9768         if (r_shadow_usingdeferredprepass)
9769                 R_Shadow_DrawPrepass();
9770
9771         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9772         {
9773                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9774                 if (r_timereport_active)
9775                         R_TimeReport("worlddepth");
9776         }
9777         if (r_depthfirst.integer >= 2)
9778         {
9779                 R_DrawModelsDepth();
9780                 if (r_timereport_active)
9781                         R_TimeReport("modeldepth");
9782         }
9783
9784         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9785         {
9786                 R_DrawModelShadowMaps();
9787                 R_ResetViewRendering3D();
9788                 // don't let sound skip if going slow
9789                 if (r_refdef.scene.extraupdate)
9790                         S_ExtraUpdate ();
9791         }
9792
9793         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9794         {
9795                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9796                 if (r_timereport_active)
9797                         R_TimeReport("world");
9798         }
9799
9800         // don't let sound skip if going slow
9801         if (r_refdef.scene.extraupdate)
9802                 S_ExtraUpdate ();
9803
9804         R_DrawModels();
9805         if (r_timereport_active)
9806                 R_TimeReport("models");
9807
9808         // don't let sound skip if going slow
9809         if (r_refdef.scene.extraupdate)
9810                 S_ExtraUpdate ();
9811
9812         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9813         {
9814                 R_DrawModelShadows();
9815                 R_ResetViewRendering3D();
9816                 // don't let sound skip if going slow
9817                 if (r_refdef.scene.extraupdate)
9818                         S_ExtraUpdate ();
9819         }
9820
9821         if (!r_shadow_usingdeferredprepass)
9822         {
9823                 R_Shadow_DrawLights();
9824                 if (r_timereport_active)
9825                         R_TimeReport("rtlights");
9826         }
9827
9828         // don't let sound skip if going slow
9829         if (r_refdef.scene.extraupdate)
9830                 S_ExtraUpdate ();
9831
9832         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9833         {
9834                 R_DrawModelShadows();
9835                 R_ResetViewRendering3D();
9836                 // don't let sound skip if going slow
9837                 if (r_refdef.scene.extraupdate)
9838                         S_ExtraUpdate ();
9839         }
9840
9841         if (cl.csqc_vidvars.drawworld)
9842         {
9843                 if (cl_decals_newsystem.integer)
9844                 {
9845                         R_DrawModelDecals();
9846                         if (r_timereport_active)
9847                                 R_TimeReport("modeldecals");
9848                 }
9849                 else
9850                 {
9851                         R_DrawDecals();
9852                         if (r_timereport_active)
9853                                 R_TimeReport("decals");
9854                 }
9855
9856                 R_DrawParticles();
9857                 if (r_timereport_active)
9858                         R_TimeReport("particles");
9859
9860                 R_DrawExplosions();
9861                 if (r_timereport_active)
9862                         R_TimeReport("explosions");
9863
9864                 R_DrawLightningBeams();
9865                 if (r_timereport_active)
9866                         R_TimeReport("lightning");
9867         }
9868
9869         VM_CL_AddPolygonsToMeshQueue();
9870
9871         if (r_refdef.view.showdebug)
9872         {
9873                 if (cl_locs_show.integer)
9874                 {
9875                         R_DrawLocs();
9876                         if (r_timereport_active)
9877                                 R_TimeReport("showlocs");
9878                 }
9879
9880                 if (r_drawportals.integer)
9881                 {
9882                         R_DrawPortals();
9883                         if (r_timereport_active)
9884                                 R_TimeReport("portals");
9885                 }
9886
9887                 if (r_showbboxes.value > 0)
9888                 {
9889                         R_DrawEntityBBoxes();
9890                         if (r_timereport_active)
9891                                 R_TimeReport("bboxes");
9892                 }
9893         }
9894
9895         R_MeshQueue_RenderTransparent();
9896         if (r_timereport_active)
9897                 R_TimeReport("drawtrans");
9898
9899         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))
9900         {
9901                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9902                 if (r_timereport_active)
9903                         R_TimeReport("worlddebug");
9904                 R_DrawModelsDebug();
9905                 if (r_timereport_active)
9906                         R_TimeReport("modeldebug");
9907         }
9908
9909         if (cl.csqc_vidvars.drawworld)
9910         {
9911                 R_Shadow_DrawCoronas();
9912                 if (r_timereport_active)
9913                         R_TimeReport("coronas");
9914         }
9915
9916         // don't let sound skip if going slow
9917         if (r_refdef.scene.extraupdate)
9918                 S_ExtraUpdate ();
9919
9920         R_ResetViewRendering2D();
9921 }
9922
9923 static const unsigned short bboxelements[36] =
9924 {
9925         5, 1, 3, 5, 3, 7,
9926         6, 2, 0, 6, 0, 4,
9927         7, 3, 2, 7, 2, 6,
9928         4, 0, 1, 4, 1, 5,
9929         4, 5, 7, 4, 7, 6,
9930         1, 0, 2, 1, 2, 3,
9931 };
9932
9933 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9934 {
9935         int i;
9936         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9937
9938         RSurf_ActiveWorldEntity();
9939
9940         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9941         GL_DepthMask(false);
9942         GL_DepthRange(0, 1);
9943         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9944         R_Mesh_ResetTextureState();
9945
9946         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9947         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9948         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9949         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9950         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9951         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9952         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9953         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9954         R_FillColors(color4f, 8, cr, cg, cb, ca);
9955         if (r_refdef.fogenabled)
9956         {
9957                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9958                 {
9959                         f1 = RSurf_FogVertex(v);
9960                         f2 = 1 - f1;
9961                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9962                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9963                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9964                 }
9965         }
9966         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9967         R_Mesh_ResetTextureState();
9968         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9969         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9970 }
9971
9972 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9973 {
9974         int i;
9975         float color[4];
9976         prvm_edict_t *edict;
9977         prvm_prog_t *prog_save = prog;
9978
9979         // this function draws bounding boxes of server entities
9980         if (!sv.active)
9981                 return;
9982
9983         GL_CullFace(GL_NONE);
9984         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9985
9986         prog = 0;
9987         SV_VM_Begin();
9988         for (i = 0;i < numsurfaces;i++)
9989         {
9990                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9991                 switch ((int)edict->fields.server->solid)
9992                 {
9993                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9994                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9995                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9996                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9997                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9998                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9999                 }
10000                 color[3] *= r_showbboxes.value;
10001                 color[3] = bound(0, color[3], 1);
10002                 GL_DepthTest(!r_showdisabledepthtest.integer);
10003                 GL_CullFace(r_refdef.view.cullface_front);
10004                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10005         }
10006         SV_VM_End();
10007         prog = prog_save;
10008 }
10009
10010 static void R_DrawEntityBBoxes(void)
10011 {
10012         int i;
10013         prvm_edict_t *edict;
10014         vec3_t center;
10015         prvm_prog_t *prog_save = prog;
10016
10017         // this function draws bounding boxes of server entities
10018         if (!sv.active)
10019                 return;
10020
10021         prog = 0;
10022         SV_VM_Begin();
10023         for (i = 0;i < prog->num_edicts;i++)
10024         {
10025                 edict = PRVM_EDICT_NUM(i);
10026                 if (edict->priv.server->free)
10027                         continue;
10028                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10029                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10030                         continue;
10031                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10032                         continue;
10033                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10034                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10035         }
10036         SV_VM_End();
10037         prog = prog_save;
10038 }
10039
10040 static const int nomodelelement3i[24] =
10041 {
10042         5, 2, 0,
10043         5, 1, 2,
10044         5, 0, 3,
10045         5, 3, 1,
10046         0, 2, 4,
10047         2, 1, 4,
10048         3, 0, 4,
10049         1, 3, 4
10050 };
10051
10052 static const unsigned short nomodelelement3s[24] =
10053 {
10054         5, 2, 0,
10055         5, 1, 2,
10056         5, 0, 3,
10057         5, 3, 1,
10058         0, 2, 4,
10059         2, 1, 4,
10060         3, 0, 4,
10061         1, 3, 4
10062 };
10063
10064 static const float nomodelvertex3f[6*3] =
10065 {
10066         -16,   0,   0,
10067          16,   0,   0,
10068           0, -16,   0,
10069           0,  16,   0,
10070           0,   0, -16,
10071           0,   0,  16
10072 };
10073
10074 static const float nomodelcolor4f[6*4] =
10075 {
10076         0.0f, 0.0f, 0.5f, 1.0f,
10077         0.0f, 0.0f, 0.5f, 1.0f,
10078         0.0f, 0.5f, 0.0f, 1.0f,
10079         0.0f, 0.5f, 0.0f, 1.0f,
10080         0.5f, 0.0f, 0.0f, 1.0f,
10081         0.5f, 0.0f, 0.0f, 1.0f
10082 };
10083
10084 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10085 {
10086         int i;
10087         float f1, f2, *c;
10088         float color4f[6*4];
10089
10090         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);
10091
10092         // this is only called once per entity so numsurfaces is always 1, and
10093         // surfacelist is always {0}, so this code does not handle batches
10094
10095         if (rsurface.ent_flags & RENDER_ADDITIVE)
10096         {
10097                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10098                 GL_DepthMask(false);
10099         }
10100         else if (rsurface.colormod[3] < 1)
10101         {
10102                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10103                 GL_DepthMask(false);
10104         }
10105         else
10106         {
10107                 GL_BlendFunc(GL_ONE, GL_ZERO);
10108                 GL_DepthMask(true);
10109         }
10110         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10111         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10112         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10113         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10114         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10115         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10116         for (i = 0, c = color4f;i < 6;i++, c += 4)
10117         {
10118                 c[0] *= rsurface.colormod[0];
10119                 c[1] *= rsurface.colormod[1];
10120                 c[2] *= rsurface.colormod[2];
10121                 c[3] *= rsurface.colormod[3];
10122         }
10123         if (r_refdef.fogenabled)
10124         {
10125                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10126                 {
10127                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10128                         f2 = 1 - f1;
10129                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10130                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10131                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10132                 }
10133         }
10134         R_Mesh_ResetTextureState();
10135         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10136         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10137 }
10138
10139 void R_DrawNoModel(entity_render_t *ent)
10140 {
10141         vec3_t org;
10142         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10143         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10144                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10145         else
10146                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10147 }
10148
10149 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10150 {
10151         vec3_t right1, right2, diff, normal;
10152
10153         VectorSubtract (org2, org1, normal);
10154
10155         // calculate 'right' vector for start
10156         VectorSubtract (r_refdef.view.origin, org1, diff);
10157         CrossProduct (normal, diff, right1);
10158         VectorNormalize (right1);
10159
10160         // calculate 'right' vector for end
10161         VectorSubtract (r_refdef.view.origin, org2, diff);
10162         CrossProduct (normal, diff, right2);
10163         VectorNormalize (right2);
10164
10165         vert[ 0] = org1[0] + width * right1[0];
10166         vert[ 1] = org1[1] + width * right1[1];
10167         vert[ 2] = org1[2] + width * right1[2];
10168         vert[ 3] = org1[0] - width * right1[0];
10169         vert[ 4] = org1[1] - width * right1[1];
10170         vert[ 5] = org1[2] - width * right1[2];
10171         vert[ 6] = org2[0] - width * right2[0];
10172         vert[ 7] = org2[1] - width * right2[1];
10173         vert[ 8] = org2[2] - width * right2[2];
10174         vert[ 9] = org2[0] + width * right2[0];
10175         vert[10] = org2[1] + width * right2[1];
10176         vert[11] = org2[2] + width * right2[2];
10177 }
10178
10179 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)
10180 {
10181         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10182         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10183         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10184         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10185         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10186         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10187         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10188         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10189         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10190         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10191         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10192         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10193 }
10194
10195 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10196 {
10197         int i;
10198         float *vertex3f;
10199         float v[3];
10200         VectorSet(v, x, y, z);
10201         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10202                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10203                         break;
10204         if (i == mesh->numvertices)
10205         {
10206                 if (mesh->numvertices < mesh->maxvertices)
10207                 {
10208                         VectorCopy(v, vertex3f);
10209                         mesh->numvertices++;
10210                 }
10211                 return mesh->numvertices;
10212         }
10213         else
10214                 return i;
10215 }
10216
10217 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10218 {
10219         int i;
10220         int *e, element[3];
10221         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10222         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10223         e = mesh->element3i + mesh->numtriangles * 3;
10224         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10225         {
10226                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10227                 if (mesh->numtriangles < mesh->maxtriangles)
10228                 {
10229                         *e++ = element[0];
10230                         *e++ = element[1];
10231                         *e++ = element[2];
10232                         mesh->numtriangles++;
10233                 }
10234                 element[1] = element[2];
10235         }
10236 }
10237
10238 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10239 {
10240         int i;
10241         int *e, element[3];
10242         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10243         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10244         e = mesh->element3i + mesh->numtriangles * 3;
10245         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10246         {
10247                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10248                 if (mesh->numtriangles < mesh->maxtriangles)
10249                 {
10250                         *e++ = element[0];
10251                         *e++ = element[1];
10252                         *e++ = element[2];
10253                         mesh->numtriangles++;
10254                 }
10255                 element[1] = element[2];
10256         }
10257 }
10258
10259 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10260 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10261 {
10262         int planenum, planenum2;
10263         int w;
10264         int tempnumpoints;
10265         mplane_t *plane, *plane2;
10266         double maxdist;
10267         double temppoints[2][256*3];
10268         // figure out how large a bounding box we need to properly compute this brush
10269         maxdist = 0;
10270         for (w = 0;w < numplanes;w++)
10271                 maxdist = max(maxdist, fabs(planes[w].dist));
10272         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10273         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10274         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10275         {
10276                 w = 0;
10277                 tempnumpoints = 4;
10278                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10279                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10280                 {
10281                         if (planenum2 == planenum)
10282                                 continue;
10283                         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);
10284                         w = !w;
10285                 }
10286                 if (tempnumpoints < 3)
10287                         continue;
10288                 // generate elements forming a triangle fan for this polygon
10289                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10290         }
10291 }
10292
10293 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)
10294 {
10295         texturelayer_t *layer;
10296         layer = t->currentlayers + t->currentnumlayers++;
10297         layer->type = type;
10298         layer->depthmask = depthmask;
10299         layer->blendfunc1 = blendfunc1;
10300         layer->blendfunc2 = blendfunc2;
10301         layer->texture = texture;
10302         layer->texmatrix = *matrix;
10303         layer->color[0] = r;
10304         layer->color[1] = g;
10305         layer->color[2] = b;
10306         layer->color[3] = a;
10307 }
10308
10309 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10310 {
10311         if(parms[0] == 0 && parms[1] == 0)
10312                 return false;
10313         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10314                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10315                         return false;
10316         return true;
10317 }
10318
10319 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10320 {
10321         double index, f;
10322         index = parms[2] + r_refdef.scene.time * parms[3];
10323         index -= floor(index);
10324         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10325         {
10326         default:
10327         case Q3WAVEFUNC_NONE:
10328         case Q3WAVEFUNC_NOISE:
10329         case Q3WAVEFUNC_COUNT:
10330                 f = 0;
10331                 break;
10332         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10333         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10334         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10335         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10336         case Q3WAVEFUNC_TRIANGLE:
10337                 index *= 4;
10338                 f = index - floor(index);
10339                 if (index < 1)
10340                         f = f;
10341                 else if (index < 2)
10342                         f = 1 - f;
10343                 else if (index < 3)
10344                         f = -f;
10345                 else
10346                         f = -(1 - f);
10347                 break;
10348         }
10349         f = parms[0] + parms[1] * f;
10350         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10351                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10352         return (float) f;
10353 }
10354
10355 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10356 {
10357         int w, h, idx;
10358         float f;
10359         float tcmat[12];
10360         matrix4x4_t matrix, temp;
10361         switch(tcmod->tcmod)
10362         {
10363                 case Q3TCMOD_COUNT:
10364                 case Q3TCMOD_NONE:
10365                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10366                                 matrix = r_waterscrollmatrix;
10367                         else
10368                                 matrix = identitymatrix;
10369                         break;
10370                 case Q3TCMOD_ENTITYTRANSLATE:
10371                         // this is used in Q3 to allow the gamecode to control texcoord
10372                         // scrolling on the entity, which is not supported in darkplaces yet.
10373                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10374                         break;
10375                 case Q3TCMOD_ROTATE:
10376                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10377                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10378                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10379                         break;
10380                 case Q3TCMOD_SCALE:
10381                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10382                         break;
10383                 case Q3TCMOD_SCROLL:
10384                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10385                         break;
10386                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10387                         w = (int) tcmod->parms[0];
10388                         h = (int) tcmod->parms[1];
10389                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10390                         f = f - floor(f);
10391                         idx = (int) floor(f * w * h);
10392                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10393                         break;
10394                 case Q3TCMOD_STRETCH:
10395                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10396                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10397                         break;
10398                 case Q3TCMOD_TRANSFORM:
10399                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10400                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10401                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10402                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10403                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10404                         break;
10405                 case Q3TCMOD_TURBULENT:
10406                         // this is handled in the RSurf_PrepareVertices function
10407                         matrix = identitymatrix;
10408                         break;
10409         }
10410         temp = *texmatrix;
10411         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10412 }
10413
10414 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10415 {
10416         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10417         char name[MAX_QPATH];
10418         skinframe_t *skinframe;
10419         unsigned char pixels[296*194];
10420         strlcpy(cache->name, skinname, sizeof(cache->name));
10421         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10422         if (developer_loading.integer)
10423                 Con_Printf("loading %s\n", name);
10424         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10425         if (!skinframe || !skinframe->base)
10426         {
10427                 unsigned char *f;
10428                 fs_offset_t filesize;
10429                 skinframe = NULL;
10430                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10431                 if (f)
10432                 {
10433                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10434                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10435                         Mem_Free(f);
10436                 }
10437         }
10438         cache->skinframe = skinframe;
10439 }
10440
10441 texture_t *R_GetCurrentTexture(texture_t *t)
10442 {
10443         int i;
10444         const entity_render_t *ent = rsurface.entity;
10445         dp_model_t *model = ent->model;
10446         q3shaderinfo_layer_tcmod_t *tcmod;
10447
10448         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10449                 return t->currentframe;
10450         t->update_lastrenderframe = r_textureframe;
10451         t->update_lastrenderentity = (void *)ent;
10452
10453         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10454                 t->camera_entity = ent->entitynumber;
10455         else
10456                 t->camera_entity = 0;
10457
10458         // switch to an alternate material if this is a q1bsp animated material
10459         {
10460                 texture_t *texture = t;
10461                 int s = rsurface.ent_skinnum;
10462                 if ((unsigned int)s >= (unsigned int)model->numskins)
10463                         s = 0;
10464                 if (model->skinscenes)
10465                 {
10466                         if (model->skinscenes[s].framecount > 1)
10467                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10468                         else
10469                                 s = model->skinscenes[s].firstframe;
10470                 }
10471                 if (s > 0)
10472                         t = t + s * model->num_surfaces;
10473                 if (t->animated)
10474                 {
10475                         // use an alternate animation if the entity's frame is not 0,
10476                         // and only if the texture has an alternate animation
10477                         if (rsurface.ent_alttextures && t->anim_total[1])
10478                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10479                         else
10480                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10481                 }
10482                 texture->currentframe = t;
10483         }
10484
10485         // update currentskinframe to be a qw skin or animation frame
10486         if (rsurface.ent_qwskin >= 0)
10487         {
10488                 i = rsurface.ent_qwskin;
10489                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10490                 {
10491                         r_qwskincache_size = cl.maxclients;
10492                         if (r_qwskincache)
10493                                 Mem_Free(r_qwskincache);
10494                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10495                 }
10496                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10497                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10498                 t->currentskinframe = r_qwskincache[i].skinframe;
10499                 if (t->currentskinframe == NULL)
10500                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10501         }
10502         else if (t->numskinframes >= 2)
10503                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10504         if (t->backgroundnumskinframes >= 2)
10505                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10506
10507         t->currentmaterialflags = t->basematerialflags;
10508         t->currentalpha = rsurface.colormod[3];
10509         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10510                 t->currentalpha *= r_wateralpha.value;
10511         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10512                 t->currentalpha *= t->r_water_wateralpha;
10513         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10514                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10515         if (!(rsurface.ent_flags & RENDER_LIGHT))
10516                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10517         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10518         {
10519                 // pick a model lighting mode
10520                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10521                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10522                 else
10523                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10524         }
10525         if (rsurface.ent_flags & RENDER_ADDITIVE)
10526                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10527         else if (t->currentalpha < 1)
10528                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10529         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10530                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10531         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10532                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10533         if (t->backgroundnumskinframes)
10534                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10535         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10536         {
10537                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10538                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10539         }
10540         else
10541                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10542         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10543                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10544
10545         // there is no tcmod
10546         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10547         {
10548                 t->currenttexmatrix = r_waterscrollmatrix;
10549                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10550         }
10551         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10552         {
10553                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10554                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10555         }
10556
10557         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10558                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10559         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10560                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10561
10562         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10563         if (t->currentskinframe->qpixels)
10564                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10565         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10566         if (!t->basetexture)
10567                 t->basetexture = r_texture_notexture;
10568         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10569         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10570         t->nmaptexture = t->currentskinframe->nmap;
10571         if (!t->nmaptexture)
10572                 t->nmaptexture = r_texture_blanknormalmap;
10573         t->glosstexture = r_texture_black;
10574         t->glowtexture = t->currentskinframe->glow;
10575         t->fogtexture = t->currentskinframe->fog;
10576         t->reflectmasktexture = t->currentskinframe->reflect;
10577         if (t->backgroundnumskinframes)
10578         {
10579                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10580                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10581                 t->backgroundglosstexture = r_texture_black;
10582                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10583                 if (!t->backgroundnmaptexture)
10584                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10585         }
10586         else
10587         {
10588                 t->backgroundbasetexture = r_texture_white;
10589                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10590                 t->backgroundglosstexture = r_texture_black;
10591                 t->backgroundglowtexture = NULL;
10592         }
10593         t->specularpower = r_shadow_glossexponent.value;
10594         // TODO: store reference values for these in the texture?
10595         t->specularscale = 0;
10596         if (r_shadow_gloss.integer > 0)
10597         {
10598                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10599                 {
10600                         if (r_shadow_glossintensity.value > 0)
10601                         {
10602                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10603                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10604                                 t->specularscale = r_shadow_glossintensity.value;
10605                         }
10606                 }
10607                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10608                 {
10609                         t->glosstexture = r_texture_white;
10610                         t->backgroundglosstexture = r_texture_white;
10611                         t->specularscale = r_shadow_gloss2intensity.value;
10612                         t->specularpower = r_shadow_gloss2exponent.value;
10613                 }
10614         }
10615         t->specularscale *= t->specularscalemod;
10616         t->specularpower *= t->specularpowermod;
10617
10618         // lightmaps mode looks bad with dlights using actual texturing, so turn
10619         // off the colormap and glossmap, but leave the normalmap on as it still
10620         // accurately represents the shading involved
10621         if (gl_lightmaps.integer)
10622         {
10623                 t->basetexture = r_texture_grey128;
10624                 t->pantstexture = r_texture_black;
10625                 t->shirttexture = r_texture_black;
10626                 t->nmaptexture = r_texture_blanknormalmap;
10627                 t->glosstexture = r_texture_black;
10628                 t->glowtexture = NULL;
10629                 t->fogtexture = NULL;
10630                 t->reflectmasktexture = NULL;
10631                 t->backgroundbasetexture = NULL;
10632                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10633                 t->backgroundglosstexture = r_texture_black;
10634                 t->backgroundglowtexture = NULL;
10635                 t->specularscale = 0;
10636                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10637         }
10638
10639         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10640         VectorClear(t->dlightcolor);
10641         t->currentnumlayers = 0;
10642         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10643         {
10644                 int blendfunc1, blendfunc2;
10645                 qboolean depthmask;
10646                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10647                 {
10648                         blendfunc1 = GL_SRC_ALPHA;
10649                         blendfunc2 = GL_ONE;
10650                 }
10651                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10652                 {
10653                         blendfunc1 = GL_SRC_ALPHA;
10654                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10655                 }
10656                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10657                 {
10658                         blendfunc1 = t->customblendfunc[0];
10659                         blendfunc2 = t->customblendfunc[1];
10660                 }
10661                 else
10662                 {
10663                         blendfunc1 = GL_ONE;
10664                         blendfunc2 = GL_ZERO;
10665                 }
10666                 // don't colormod evilblend textures
10667                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10668                         VectorSet(t->lightmapcolor, 1, 1, 1);
10669                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10670                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10671                 {
10672                         // fullbright is not affected by r_refdef.lightmapintensity
10673                         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]);
10674                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10675                                 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]);
10676                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10677                                 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]);
10678                 }
10679                 else
10680                 {
10681                         vec3_t ambientcolor;
10682                         float colorscale;
10683                         // set the color tint used for lights affecting this surface
10684                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10685                         colorscale = 2;
10686                         // q3bsp has no lightmap updates, so the lightstylevalue that
10687                         // would normally be baked into the lightmap must be
10688                         // applied to the color
10689                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10690                         if (model->type == mod_brushq3)
10691                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10692                         colorscale *= r_refdef.lightmapintensity;
10693                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10694                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10695                         // basic lit geometry
10696                         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]);
10697                         // add pants/shirt if needed
10698                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10699                                 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]);
10700                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10701                                 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]);
10702                         // now add ambient passes if needed
10703                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10704                         {
10705                                 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]);
10706                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10707                                         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]);
10708                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10709                                         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]);
10710                         }
10711                 }
10712                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10713                         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]);
10714                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10715                 {
10716                         // if this is opaque use alpha blend which will darken the earlier
10717                         // passes cheaply.
10718                         //
10719                         // if this is an alpha blended material, all the earlier passes
10720                         // were darkened by fog already, so we only need to add the fog
10721                         // color ontop through the fog mask texture
10722                         //
10723                         // if this is an additive blended material, all the earlier passes
10724                         // were darkened by fog already, and we should not add fog color
10725                         // (because the background was not darkened, there is no fog color
10726                         // that was lost behind it).
10727                         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]);
10728                 }
10729         }
10730
10731         return t->currentframe;
10732 }
10733
10734 rsurfacestate_t rsurface;
10735
10736 void R_Mesh_ResizeArrays(int newvertices)
10737 {
10738         unsigned char *base;
10739         size_t size;
10740         if (rsurface.array_size >= newvertices)
10741                 return;
10742         if (rsurface.array_base)
10743                 Mem_Free(rsurface.array_base);
10744         rsurface.array_size = (newvertices + 1023) & ~1023;
10745         size = 0;
10746         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10747         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10748         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10749         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10750         size += rsurface.array_size * sizeof(float[3]);
10751         size += rsurface.array_size * sizeof(float[3]);
10752         size += rsurface.array_size * sizeof(float[3]);
10753         size += rsurface.array_size * sizeof(float[3]);
10754         size += rsurface.array_size * sizeof(float[3]);
10755         size += rsurface.array_size * sizeof(float[3]);
10756         size += rsurface.array_size * sizeof(float[3]);
10757         size += rsurface.array_size * sizeof(float[3]);
10758         size += rsurface.array_size * sizeof(float[4]);
10759         size += rsurface.array_size * sizeof(float[2]);
10760         size += rsurface.array_size * sizeof(float[2]);
10761         size += rsurface.array_size * sizeof(float[4]);
10762         size += rsurface.array_size * sizeof(int[3]);
10763         size += rsurface.array_size * sizeof(unsigned short[3]);
10764         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10765         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10766         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10767         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10768         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10769         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10770         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10771         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10772         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10773         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10774         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10775         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10776         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10777         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10778         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10779         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10780         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10781         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10782         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10783 }
10784
10785 void RSurf_ActiveWorldEntity(void)
10786 {
10787         dp_model_t *model = r_refdef.scene.worldmodel;
10788         //if (rsurface.entity == r_refdef.scene.worldentity)
10789         //      return;
10790         rsurface.entity = r_refdef.scene.worldentity;
10791         rsurface.skeleton = NULL;
10792         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10793         rsurface.ent_skinnum = 0;
10794         rsurface.ent_qwskin = -1;
10795         rsurface.ent_shadertime = 0;
10796         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10797         if (rsurface.array_size < model->surfmesh.num_vertices)
10798                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10799         rsurface.matrix = identitymatrix;
10800         rsurface.inversematrix = identitymatrix;
10801         rsurface.matrixscale = 1;
10802         rsurface.inversematrixscale = 1;
10803         R_EntityMatrix(&identitymatrix);
10804         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10805         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10806         rsurface.fograngerecip = r_refdef.fograngerecip;
10807         rsurface.fogheightfade = r_refdef.fogheightfade;
10808         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10809         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10810         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10811         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10812         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10813         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10814         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10815         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10816         rsurface.colormod[3] = 1;
10817         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);
10818         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10819         rsurface.frameblend[0].lerp = 1;
10820         rsurface.ent_alttextures = false;
10821         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10822         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10823         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10824         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10825         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10826         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10827         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10828         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10829         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10830         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10831         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10832         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10833         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10834         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10835         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10836         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10837         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10838         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10839         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10840         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10841         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10842         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10843         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10844         rsurface.modelelement3i = model->surfmesh.data_element3i;
10845         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10846         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10847         rsurface.modelelement3s = model->surfmesh.data_element3s;
10848         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10849         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10850         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10851         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10852         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10853         rsurface.modelsurfaces = model->data_surfaces;
10854         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10855         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10856         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10857         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10858         rsurface.modelgeneratedvertex = false;
10859         rsurface.batchgeneratedvertex = false;
10860         rsurface.batchfirstvertex = 0;
10861         rsurface.batchnumvertices = 0;
10862         rsurface.batchfirsttriangle = 0;
10863         rsurface.batchnumtriangles = 0;
10864         rsurface.batchvertex3f  = NULL;
10865         rsurface.batchvertex3f_vertexbuffer = NULL;
10866         rsurface.batchvertex3f_bufferoffset = 0;
10867         rsurface.batchsvector3f = NULL;
10868         rsurface.batchsvector3f_vertexbuffer = NULL;
10869         rsurface.batchsvector3f_bufferoffset = 0;
10870         rsurface.batchtvector3f = NULL;
10871         rsurface.batchtvector3f_vertexbuffer = NULL;
10872         rsurface.batchtvector3f_bufferoffset = 0;
10873         rsurface.batchnormal3f  = NULL;
10874         rsurface.batchnormal3f_vertexbuffer = NULL;
10875         rsurface.batchnormal3f_bufferoffset = 0;
10876         rsurface.batchlightmapcolor4f = NULL;
10877         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10878         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10879         rsurface.batchtexcoordtexture2f = NULL;
10880         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10881         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10882         rsurface.batchtexcoordlightmap2f = NULL;
10883         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10884         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10885         rsurface.batchvertexmesh = NULL;
10886         rsurface.batchvertexmeshbuffer = NULL;
10887         rsurface.batchvertexposition = NULL;
10888         rsurface.batchvertexpositionbuffer = NULL;
10889         rsurface.batchelement3i = NULL;
10890         rsurface.batchelement3i_indexbuffer = NULL;
10891         rsurface.batchelement3i_bufferoffset = 0;
10892         rsurface.batchelement3s = NULL;
10893         rsurface.batchelement3s_indexbuffer = NULL;
10894         rsurface.batchelement3s_bufferoffset = 0;
10895         rsurface.passcolor4f = NULL;
10896         rsurface.passcolor4f_vertexbuffer = NULL;
10897         rsurface.passcolor4f_bufferoffset = 0;
10898 }
10899
10900 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10901 {
10902         dp_model_t *model = ent->model;
10903         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10904         //      return;
10905         rsurface.entity = (entity_render_t *)ent;
10906         rsurface.skeleton = ent->skeleton;
10907         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10908         rsurface.ent_skinnum = ent->skinnum;
10909         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;
10910         rsurface.ent_shadertime = ent->shadertime;
10911         rsurface.ent_flags = ent->flags;
10912         if (rsurface.array_size < model->surfmesh.num_vertices)
10913                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10914         rsurface.matrix = ent->matrix;
10915         rsurface.inversematrix = ent->inversematrix;
10916         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10917         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10918         R_EntityMatrix(&rsurface.matrix);
10919         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10920         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10921         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10922         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10923         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10924         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10925         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10926         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10927         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10928         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10929         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10930         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10931         rsurface.colormod[3] = ent->alpha;
10932         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10933         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10934         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10935         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10936         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10937         if (ent->model->brush.submodel && !prepass)
10938         {
10939                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10940                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10941         }
10942         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10943         {
10944                 if (ent->animcache_vertex3f && !r_framedata_failed)
10945                 {
10946                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10947                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10948                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10949                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10950                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10951                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10952                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10953                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10954                 }
10955                 else if (wanttangents)
10956                 {
10957                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10958                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10959                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10960                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10961                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10962                         rsurface.modelvertexmesh = NULL;
10963                         rsurface.modelvertexmeshbuffer = NULL;
10964                         rsurface.modelvertexposition = NULL;
10965                         rsurface.modelvertexpositionbuffer = NULL;
10966                 }
10967                 else if (wantnormals)
10968                 {
10969                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10970                         rsurface.modelsvector3f = NULL;
10971                         rsurface.modeltvector3f = NULL;
10972                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10973                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10974                         rsurface.modelvertexmesh = NULL;
10975                         rsurface.modelvertexmeshbuffer = NULL;
10976                         rsurface.modelvertexposition = NULL;
10977                         rsurface.modelvertexpositionbuffer = NULL;
10978                 }
10979                 else
10980                 {
10981                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10982                         rsurface.modelsvector3f = NULL;
10983                         rsurface.modeltvector3f = NULL;
10984                         rsurface.modelnormal3f = NULL;
10985                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10986                         rsurface.modelvertexmesh = NULL;
10987                         rsurface.modelvertexmeshbuffer = NULL;
10988                         rsurface.modelvertexposition = NULL;
10989                         rsurface.modelvertexpositionbuffer = NULL;
10990                 }
10991                 rsurface.modelvertex3f_vertexbuffer = 0;
10992                 rsurface.modelvertex3f_bufferoffset = 0;
10993                 rsurface.modelsvector3f_vertexbuffer = 0;
10994                 rsurface.modelsvector3f_bufferoffset = 0;
10995                 rsurface.modeltvector3f_vertexbuffer = 0;
10996                 rsurface.modeltvector3f_bufferoffset = 0;
10997                 rsurface.modelnormal3f_vertexbuffer = 0;
10998                 rsurface.modelnormal3f_bufferoffset = 0;
10999                 rsurface.modelgeneratedvertex = true;
11000         }
11001         else
11002         {
11003                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11004                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11005                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11006                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11007                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11008                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11009                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11010                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11011                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11012                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11013                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11014                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11015                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11016                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11017                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
11018                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
11019                 rsurface.modelgeneratedvertex = false;
11020         }
11021         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11022         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11023         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11024         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11025         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11026         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11027         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11028         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11029         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11030         rsurface.modelelement3i = model->surfmesh.data_element3i;
11031         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11032         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11033         rsurface.modelelement3s = model->surfmesh.data_element3s;
11034         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11035         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11036         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11037         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11038         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11039         rsurface.modelsurfaces = model->data_surfaces;
11040         rsurface.batchgeneratedvertex = false;
11041         rsurface.batchfirstvertex = 0;
11042         rsurface.batchnumvertices = 0;
11043         rsurface.batchfirsttriangle = 0;
11044         rsurface.batchnumtriangles = 0;
11045         rsurface.batchvertex3f  = NULL;
11046         rsurface.batchvertex3f_vertexbuffer = NULL;
11047         rsurface.batchvertex3f_bufferoffset = 0;
11048         rsurface.batchsvector3f = NULL;
11049         rsurface.batchsvector3f_vertexbuffer = NULL;
11050         rsurface.batchsvector3f_bufferoffset = 0;
11051         rsurface.batchtvector3f = NULL;
11052         rsurface.batchtvector3f_vertexbuffer = NULL;
11053         rsurface.batchtvector3f_bufferoffset = 0;
11054         rsurface.batchnormal3f  = NULL;
11055         rsurface.batchnormal3f_vertexbuffer = NULL;
11056         rsurface.batchnormal3f_bufferoffset = 0;
11057         rsurface.batchlightmapcolor4f = NULL;
11058         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11059         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11060         rsurface.batchtexcoordtexture2f = NULL;
11061         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11062         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11063         rsurface.batchtexcoordlightmap2f = NULL;
11064         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11065         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11066         rsurface.batchvertexmesh = NULL;
11067         rsurface.batchvertexmeshbuffer = NULL;
11068         rsurface.batchvertexposition = NULL;
11069         rsurface.batchvertexpositionbuffer = NULL;
11070         rsurface.batchelement3i = NULL;
11071         rsurface.batchelement3i_indexbuffer = NULL;
11072         rsurface.batchelement3i_bufferoffset = 0;
11073         rsurface.batchelement3s = NULL;
11074         rsurface.batchelement3s_indexbuffer = NULL;
11075         rsurface.batchelement3s_bufferoffset = 0;
11076         rsurface.passcolor4f = NULL;
11077         rsurface.passcolor4f_vertexbuffer = NULL;
11078         rsurface.passcolor4f_bufferoffset = 0;
11079 }
11080
11081 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)
11082 {
11083         int i;
11084
11085         rsurface.entity = r_refdef.scene.worldentity;
11086         rsurface.skeleton = NULL;
11087         rsurface.ent_skinnum = 0;
11088         rsurface.ent_qwskin = -1;
11089         rsurface.ent_shadertime = shadertime;
11090         rsurface.ent_flags = entflags;
11091         rsurface.modelnumvertices = numvertices;
11092         rsurface.modelnumtriangles = numtriangles;
11093         if (rsurface.array_size < rsurface.modelnumvertices)
11094                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
11095         rsurface.matrix = *matrix;
11096         rsurface.inversematrix = *inversematrix;
11097         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11098         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11099         R_EntityMatrix(&rsurface.matrix);
11100         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11101         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11102         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11103         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11104         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11105         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11106         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11107         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11108         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11109         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11110         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11111         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11112         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);
11113         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11114         rsurface.frameblend[0].lerp = 1;
11115         rsurface.ent_alttextures = false;
11116         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11117         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11118         if (wanttangents)
11119         {
11120                 rsurface.modelvertex3f = vertex3f;
11121                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
11122                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
11123                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11124         }
11125         else if (wantnormals)
11126         {
11127                 rsurface.modelvertex3f = vertex3f;
11128                 rsurface.modelsvector3f = NULL;
11129                 rsurface.modeltvector3f = NULL;
11130                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
11131         }
11132         else
11133         {
11134                 rsurface.modelvertex3f = vertex3f;
11135                 rsurface.modelsvector3f = NULL;
11136                 rsurface.modeltvector3f = NULL;
11137                 rsurface.modelnormal3f = NULL;
11138         }
11139         rsurface.modelvertexmesh = NULL;
11140         rsurface.modelvertexmeshbuffer = NULL;
11141         rsurface.modelvertexposition = NULL;
11142         rsurface.modelvertexpositionbuffer = NULL;
11143         rsurface.modelvertex3f_vertexbuffer = 0;
11144         rsurface.modelvertex3f_bufferoffset = 0;
11145         rsurface.modelsvector3f_vertexbuffer = 0;
11146         rsurface.modelsvector3f_bufferoffset = 0;
11147         rsurface.modeltvector3f_vertexbuffer = 0;
11148         rsurface.modeltvector3f_bufferoffset = 0;
11149         rsurface.modelnormal3f_vertexbuffer = 0;
11150         rsurface.modelnormal3f_bufferoffset = 0;
11151         rsurface.modelgeneratedvertex = true;
11152         rsurface.modellightmapcolor4f  = color4f;
11153         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11154         rsurface.modellightmapcolor4f_bufferoffset = 0;
11155         rsurface.modeltexcoordtexture2f  = texcoord2f;
11156         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11157         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11158         rsurface.modeltexcoordlightmap2f  = NULL;
11159         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11160         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11161         rsurface.modelelement3i = element3i;
11162         rsurface.modelelement3i_indexbuffer = NULL;
11163         rsurface.modelelement3i_bufferoffset = 0;
11164         rsurface.modelelement3s = element3s;
11165         rsurface.modelelement3s_indexbuffer = NULL;
11166         rsurface.modelelement3s_bufferoffset = 0;
11167         rsurface.modellightmapoffsets = NULL;
11168         rsurface.modelsurfaces = NULL;
11169         rsurface.batchgeneratedvertex = false;
11170         rsurface.batchfirstvertex = 0;
11171         rsurface.batchnumvertices = 0;
11172         rsurface.batchfirsttriangle = 0;
11173         rsurface.batchnumtriangles = 0;
11174         rsurface.batchvertex3f  = NULL;
11175         rsurface.batchvertex3f_vertexbuffer = NULL;
11176         rsurface.batchvertex3f_bufferoffset = 0;
11177         rsurface.batchsvector3f = NULL;
11178         rsurface.batchsvector3f_vertexbuffer = NULL;
11179         rsurface.batchsvector3f_bufferoffset = 0;
11180         rsurface.batchtvector3f = NULL;
11181         rsurface.batchtvector3f_vertexbuffer = NULL;
11182         rsurface.batchtvector3f_bufferoffset = 0;
11183         rsurface.batchnormal3f  = NULL;
11184         rsurface.batchnormal3f_vertexbuffer = NULL;
11185         rsurface.batchnormal3f_bufferoffset = 0;
11186         rsurface.batchlightmapcolor4f = NULL;
11187         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11188         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11189         rsurface.batchtexcoordtexture2f = NULL;
11190         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11191         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11192         rsurface.batchtexcoordlightmap2f = NULL;
11193         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11194         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11195         rsurface.batchvertexmesh = NULL;
11196         rsurface.batchvertexmeshbuffer = NULL;
11197         rsurface.batchvertexposition = NULL;
11198         rsurface.batchvertexpositionbuffer = NULL;
11199         rsurface.batchelement3i = NULL;
11200         rsurface.batchelement3i_indexbuffer = NULL;
11201         rsurface.batchelement3i_bufferoffset = 0;
11202         rsurface.batchelement3s = NULL;
11203         rsurface.batchelement3s_indexbuffer = NULL;
11204         rsurface.batchelement3s_bufferoffset = 0;
11205         rsurface.passcolor4f = NULL;
11206         rsurface.passcolor4f_vertexbuffer = NULL;
11207         rsurface.passcolor4f_bufferoffset = 0;
11208
11209         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11210         {
11211                 if ((wantnormals || wanttangents) && !normal3f)
11212                 {
11213                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11214                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
11215                 }
11216                 if (wanttangents && !svector3f)
11217                 {
11218                         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);
11219                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
11220                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
11221                 }
11222         }
11223
11224         // now convert arrays into vertexmesh structs
11225         for (i = 0;i < numvertices;i++)
11226         {
11227                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
11228                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
11229                 if (rsurface.modelsvector3f)
11230                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
11231                 if (rsurface.modeltvector3f)
11232                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
11233                 if (rsurface.modelnormal3f)
11234                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
11235                 if (rsurface.modellightmapcolor4f)
11236                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
11237                 if (rsurface.modeltexcoordtexture2f)
11238                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
11239                 if (rsurface.modeltexcoordlightmap2f)
11240                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
11241         }
11242 }
11243
11244 float RSurf_FogPoint(const float *v)
11245 {
11246         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11247         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11248         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11249         float FogHeightFade = r_refdef.fogheightfade;
11250         float fogfrac;
11251         unsigned int fogmasktableindex;
11252         if (r_refdef.fogplaneviewabove)
11253                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11254         else
11255                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11256         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11257         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11258 }
11259
11260 float RSurf_FogVertex(const float *v)
11261 {
11262         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11263         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11264         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11265         float FogHeightFade = rsurface.fogheightfade;
11266         float fogfrac;
11267         unsigned int fogmasktableindex;
11268         if (r_refdef.fogplaneviewabove)
11269                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11270         else
11271                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11272         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11273         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11274 }
11275
11276 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11277 {
11278         int i;
11279         for (i = 0;i < numelements;i++)
11280                 outelement3i[i] = inelement3i[i] + adjust;
11281 }
11282
11283 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11284 extern cvar_t gl_vbo;
11285 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11286 {
11287         int deformindex;
11288         int firsttriangle;
11289         int numtriangles;
11290         int firstvertex;
11291         int endvertex;
11292         int numvertices;
11293         int surfacefirsttriangle;
11294         int surfacenumtriangles;
11295         int surfacefirstvertex;
11296         int surfaceendvertex;
11297         int surfacenumvertices;
11298         int surfaceadjustvertex;
11299         int needsupdate;
11300         int i, j;
11301         qboolean gaps;
11302         qboolean dynamicvertex;
11303         float amplitude;
11304         float animpos;
11305         float scale;
11306         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11307         float waveparms[4];
11308         q3shaderinfo_deform_t *deform;
11309         const msurface_t *surface, *firstsurface;
11310         r_vertexposition_t *vertexposition;
11311         r_vertexmesh_t *vertexmesh;
11312         if (!texturenumsurfaces)
11313                 return;
11314         // find vertex range of this surface batch
11315         gaps = false;
11316         firstsurface = texturesurfacelist[0];
11317         firsttriangle = firstsurface->num_firsttriangle;
11318         numtriangles = 0;
11319         firstvertex = endvertex = firstsurface->num_firstvertex;
11320         for (i = 0;i < texturenumsurfaces;i++)
11321         {
11322                 surface = texturesurfacelist[i];
11323                 if (surface != firstsurface + i)
11324                         gaps = true;
11325                 surfacefirstvertex = surface->num_firstvertex;
11326                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11327                 surfacenumtriangles = surface->num_triangles;
11328                 if (firstvertex > surfacefirstvertex)
11329                         firstvertex = surfacefirstvertex;
11330                 if (endvertex < surfaceendvertex)
11331                         endvertex = surfaceendvertex;
11332                 numtriangles += surfacenumtriangles;
11333         }
11334         if (!numtriangles)
11335                 return;
11336
11337         // we now know the vertex range used, and if there are any gaps in it
11338         rsurface.batchfirstvertex = firstvertex;
11339         rsurface.batchnumvertices = endvertex - firstvertex;
11340         rsurface.batchfirsttriangle = firsttriangle;
11341         rsurface.batchnumtriangles = numtriangles;
11342
11343         // this variable holds flags for which properties have been updated that
11344         // may require regenerating vertexmesh or vertexposition arrays...
11345         needsupdate = 0;
11346
11347         // check if any dynamic vertex processing must occur
11348         dynamicvertex = false;
11349
11350         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11351                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11352         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11353         {
11354                 switch (deform->deform)
11355                 {
11356                 default:
11357                 case Q3DEFORM_PROJECTIONSHADOW:
11358                 case Q3DEFORM_TEXT0:
11359                 case Q3DEFORM_TEXT1:
11360                 case Q3DEFORM_TEXT2:
11361                 case Q3DEFORM_TEXT3:
11362                 case Q3DEFORM_TEXT4:
11363                 case Q3DEFORM_TEXT5:
11364                 case Q3DEFORM_TEXT6:
11365                 case Q3DEFORM_TEXT7:
11366                 case Q3DEFORM_NONE:
11367                         break;
11368                 case Q3DEFORM_AUTOSPRITE:
11369                         dynamicvertex = true;
11370                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11371                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11372                         break;
11373                 case Q3DEFORM_AUTOSPRITE2:
11374                         dynamicvertex = true;
11375                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11376                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11377                         break;
11378                 case Q3DEFORM_NORMAL:
11379                         dynamicvertex = true;
11380                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11381                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11382                         break;
11383                 case Q3DEFORM_WAVE:
11384                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11385                                 break; // if wavefunc is a nop, ignore this transform
11386                         dynamicvertex = true;
11387                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11388                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11389                         break;
11390                 case Q3DEFORM_BULGE:
11391                         dynamicvertex = true;
11392                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11393                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11394                         break;
11395                 case Q3DEFORM_MOVE:
11396                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11397                                 break; // if wavefunc is a nop, ignore this transform
11398                         dynamicvertex = true;
11399                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11400                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11401                         break;
11402                 }
11403         }
11404         switch(rsurface.texture->tcgen.tcgen)
11405         {
11406         default:
11407         case Q3TCGEN_TEXTURE:
11408                 break;
11409         case Q3TCGEN_LIGHTMAP:
11410                 dynamicvertex = true;
11411                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11412                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11413                 break;
11414         case Q3TCGEN_VECTOR:
11415                 dynamicvertex = true;
11416                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11417                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11418                 break;
11419         case Q3TCGEN_ENVIRONMENT:
11420                 dynamicvertex = true;
11421                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11422                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11423                 break;
11424         }
11425         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11426         {
11427                 dynamicvertex = true;
11428                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11429                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11430         }
11431
11432         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11433         {
11434                 dynamicvertex = true;
11435                 batchneed |= BATCHNEED_NOGAPS;
11436                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11437         }
11438
11439         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11440         {
11441                 dynamicvertex = true;
11442                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11443                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11444         }
11445
11446         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11447         {
11448                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11449                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11450                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11451                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11452                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11453                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11454                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11455         }
11456
11457         // when the model data has no vertex buffer (dynamic mesh), we need to
11458         // eliminate gaps
11459         if (!rsurface.modelvertexmeshbuffer)
11460                 batchneed |= BATCHNEED_NOGAPS;
11461
11462         // if needsupdate, we have to do a dynamic vertex batch for sure
11463         if (needsupdate & batchneed)
11464                 dynamicvertex = true;
11465
11466         // see if we need to build vertexmesh from arrays
11467         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11468                 dynamicvertex = true;
11469
11470         // see if we need to build vertexposition from arrays
11471         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11472                 dynamicvertex = true;
11473
11474         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11475         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11476                 dynamicvertex = true;
11477
11478         // if there is a chance of animated vertex colors, it's a dynamic batch
11479         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11480                 dynamicvertex = true;
11481
11482         rsurface.batchvertex3f = rsurface.modelvertex3f;
11483         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11484         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11485         rsurface.batchsvector3f = rsurface.modelsvector3f;
11486         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11487         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11488         rsurface.batchtvector3f = rsurface.modeltvector3f;
11489         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11490         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11491         rsurface.batchnormal3f = rsurface.modelnormal3f;
11492         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11493         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11494         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11495         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11496         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11497         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11498         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11499         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11500         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11501         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11502         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11503         rsurface.batchvertexposition = rsurface.modelvertexposition;
11504         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11505         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11506         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11507         rsurface.batchelement3i = rsurface.modelelement3i;
11508         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11509         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11510         rsurface.batchelement3s = rsurface.modelelement3s;
11511         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11512         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11513
11514         // if any dynamic vertex processing has to occur in software, we copy the
11515         // entire surface list together before processing to rebase the vertices
11516         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11517         //
11518         // if any gaps exist and we do not have a static vertex buffer, we have to
11519         // copy the surface list together to avoid wasting upload bandwidth on the
11520         // vertices in the gaps.
11521         //
11522         // if gaps exist and we have a static vertex buffer, we still have to
11523         // combine the index buffer ranges into one dynamic index buffer.
11524         //
11525         // in all cases we end up with data that can be drawn in one call.
11526
11527         if (!dynamicvertex)
11528         {
11529                 // static vertex data, just set pointers...
11530                 rsurface.batchgeneratedvertex = false;
11531                 // if there are gaps, we want to build a combined index buffer,
11532                 // otherwise use the original static buffer with an appropriate offset
11533                 if (gaps)
11534                 {
11535                         firsttriangle = 0;
11536                         numtriangles = 0;
11537                         for (i = 0;i < texturenumsurfaces;i++)
11538                         {
11539                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11540                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11541                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11542                                 numtriangles += surfacenumtriangles;
11543                         }
11544                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11545                         rsurface.batchelement3i_indexbuffer = NULL;
11546                         rsurface.batchelement3i_bufferoffset = 0;
11547                         rsurface.batchelement3s = NULL;
11548                         rsurface.batchelement3s_indexbuffer = NULL;
11549                         rsurface.batchelement3s_bufferoffset = 0;
11550                         if (endvertex <= 65536)
11551                         {
11552                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11553                                 for (i = 0;i < numtriangles*3;i++)
11554                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11555                         }
11556                         rsurface.batchfirsttriangle = firsttriangle;
11557                         rsurface.batchnumtriangles = numtriangles;
11558                 }
11559                 return;
11560         }
11561
11562         // something needs software processing, do it for real...
11563         // we only directly handle interleaved array data in this case...
11564         rsurface.batchgeneratedvertex = true;
11565
11566         // now copy the vertex data into a combined array and make an index array
11567         // (this is what Quake3 does all the time)
11568         //if (gaps || rsurface.batchfirstvertex)
11569         {
11570                 rsurface.batchvertexposition = NULL;
11571                 rsurface.batchvertexpositionbuffer = NULL;
11572                 rsurface.batchvertexmesh = NULL;
11573                 rsurface.batchvertexmeshbuffer = NULL;
11574                 rsurface.batchvertex3f = NULL;
11575                 rsurface.batchvertex3f_vertexbuffer = NULL;
11576                 rsurface.batchvertex3f_bufferoffset = 0;
11577                 rsurface.batchsvector3f = NULL;
11578                 rsurface.batchsvector3f_vertexbuffer = NULL;
11579                 rsurface.batchsvector3f_bufferoffset = 0;
11580                 rsurface.batchtvector3f = NULL;
11581                 rsurface.batchtvector3f_vertexbuffer = NULL;
11582                 rsurface.batchtvector3f_bufferoffset = 0;
11583                 rsurface.batchnormal3f = NULL;
11584                 rsurface.batchnormal3f_vertexbuffer = NULL;
11585                 rsurface.batchnormal3f_bufferoffset = 0;
11586                 rsurface.batchlightmapcolor4f = NULL;
11587                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11588                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11589                 rsurface.batchtexcoordtexture2f = NULL;
11590                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11591                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11592                 rsurface.batchtexcoordlightmap2f = NULL;
11593                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11594                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11595                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11596                 rsurface.batchelement3i_indexbuffer = NULL;
11597                 rsurface.batchelement3i_bufferoffset = 0;
11598                 rsurface.batchelement3s = NULL;
11599                 rsurface.batchelement3s_indexbuffer = NULL;
11600                 rsurface.batchelement3s_bufferoffset = 0;
11601                 // we'll only be setting up certain arrays as needed
11602                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11603                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11604                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11605                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11606                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11607                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11608                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11609                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11610                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11611                 {
11612                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11613                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11614                 }
11615                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11616                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11617                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11618                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11619                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11620                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11621                 numvertices = 0;
11622                 numtriangles = 0;
11623                 for (i = 0;i < texturenumsurfaces;i++)
11624                 {
11625                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11626                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11627                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11628                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11629                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11630                         // copy only the data requested
11631                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11632                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11633                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11634                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11635                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11636                         {
11637                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11638                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11639                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11640                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11641                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11642                                 {
11643                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11644                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11645                                 }
11646                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11647                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11648                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11649                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11650                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11651                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11652                         }
11653                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11654                         numvertices += surfacenumvertices;
11655                         numtriangles += surfacenumtriangles;
11656                 }
11657
11658                 // generate a 16bit index array as well if possible
11659                 // (in general, dynamic batches fit)
11660                 if (numvertices <= 65536)
11661                 {
11662                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11663                         for (i = 0;i < numtriangles*3;i++)
11664                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11665                 }
11666
11667                 // since we've copied everything, the batch now starts at 0
11668                 rsurface.batchfirstvertex = 0;
11669                 rsurface.batchnumvertices = numvertices;
11670                 rsurface.batchfirsttriangle = 0;
11671                 rsurface.batchnumtriangles = numtriangles;
11672         }
11673
11674         // q1bsp surfaces rendered in vertex color mode have to have colors
11675         // calculated based on lightstyles
11676         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11677         {
11678                 // generate color arrays for the surfaces in this list
11679                 int c[4];
11680                 int scale;
11681                 int size3;
11682                 const int *offsets;
11683                 const unsigned char *lm;
11684                 numvertices = 0;
11685                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11686                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11687                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11688                 for (i = 0;i < texturenumsurfaces;i++)
11689                 {
11690                         surface = texturesurfacelist[i];
11691                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11692                         surfacenumvertices = surface->num_vertices;
11693                         if (surface->lightmapinfo->samples)
11694                         {
11695                                 for (j = 0;j < surfacenumvertices;j++)
11696                                 {
11697                                         lm = surface->lightmapinfo->samples + offsets[j];
11698                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11699                                         VectorScale(lm, scale, c);
11700                                         if (surface->lightmapinfo->styles[1] != 255)
11701                                         {
11702                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11703                                                 lm += size3;
11704                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11705                                                 VectorMA(c, scale, lm, c);
11706                                                 if (surface->lightmapinfo->styles[2] != 255)
11707                                                 {
11708                                                         lm += size3;
11709                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11710                                                         VectorMA(c, scale, lm, c);
11711                                                         if (surface->lightmapinfo->styles[3] != 255)
11712                                                         {
11713                                                                 lm += size3;
11714                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11715                                                                 VectorMA(c, scale, lm, c);
11716                                                         }
11717                                                 }
11718                                         }
11719                                         c[0] >>= 15;
11720                                         c[1] >>= 15;
11721                                         c[2] >>= 15;
11722                                         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);
11723                                         numvertices++;
11724                                 }
11725                         }
11726                         else
11727                         {
11728                                 for (j = 0;j < surfacenumvertices;j++)
11729                                 {
11730                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11731                                         numvertices++;
11732                                 }
11733                         }
11734                 }
11735         }
11736
11737         // if vertices are deformed (sprite flares and things in maps, possibly
11738         // water waves, bulges and other deformations), modify the copied vertices
11739         // in place
11740         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11741         {
11742                 switch (deform->deform)
11743                 {
11744                 default:
11745                 case Q3DEFORM_PROJECTIONSHADOW:
11746                 case Q3DEFORM_TEXT0:
11747                 case Q3DEFORM_TEXT1:
11748                 case Q3DEFORM_TEXT2:
11749                 case Q3DEFORM_TEXT3:
11750                 case Q3DEFORM_TEXT4:
11751                 case Q3DEFORM_TEXT5:
11752                 case Q3DEFORM_TEXT6:
11753                 case Q3DEFORM_TEXT7:
11754                 case Q3DEFORM_NONE:
11755                         break;
11756                 case Q3DEFORM_AUTOSPRITE:
11757                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11758                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11759                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11760                         VectorNormalize(newforward);
11761                         VectorNormalize(newright);
11762                         VectorNormalize(newup);
11763                         // a single autosprite surface can contain multiple sprites...
11764                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11765                         {
11766                                 VectorClear(center);
11767                                 for (i = 0;i < 4;i++)
11768                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11769                                 VectorScale(center, 0.25f, center);
11770                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11771                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11772                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11773                                 for (i = 0;i < 4;i++)
11774                                 {
11775                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11776                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11777                                 }
11778                         }
11779                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11780                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11781                         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);
11782                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11783                         rsurface.batchvertex3f_vertexbuffer = NULL;
11784                         rsurface.batchvertex3f_bufferoffset = 0;
11785                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11786                         rsurface.batchsvector3f_vertexbuffer = NULL;
11787                         rsurface.batchsvector3f_bufferoffset = 0;
11788                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11789                         rsurface.batchtvector3f_vertexbuffer = NULL;
11790                         rsurface.batchtvector3f_bufferoffset = 0;
11791                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11792                         rsurface.batchnormal3f_vertexbuffer = NULL;
11793                         rsurface.batchnormal3f_bufferoffset = 0;
11794                         break;
11795                 case Q3DEFORM_AUTOSPRITE2:
11796                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11797                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11798                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11799                         VectorNormalize(newforward);
11800                         VectorNormalize(newright);
11801                         VectorNormalize(newup);
11802                         {
11803                                 const float *v1, *v2;
11804                                 vec3_t start, end;
11805                                 float f, l;
11806                                 struct
11807                                 {
11808                                         float length2;
11809                                         const float *v1;
11810                                         const float *v2;
11811                                 }
11812                                 shortest[2];
11813                                 memset(shortest, 0, sizeof(shortest));
11814                                 // a single autosprite surface can contain multiple sprites...
11815                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11816                                 {
11817                                         VectorClear(center);
11818                                         for (i = 0;i < 4;i++)
11819                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11820                                         VectorScale(center, 0.25f, center);
11821                                         // find the two shortest edges, then use them to define the
11822                                         // axis vectors for rotating around the central axis
11823                                         for (i = 0;i < 6;i++)
11824                                         {
11825                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11826                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11827                                                 l = VectorDistance2(v1, v2);
11828                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11829                                                 if (v1[2] != v2[2])
11830                                                         l += (1.0f / 1024.0f);
11831                                                 if (shortest[0].length2 > l || i == 0)
11832                                                 {
11833                                                         shortest[1] = shortest[0];
11834                                                         shortest[0].length2 = l;
11835                                                         shortest[0].v1 = v1;
11836                                                         shortest[0].v2 = v2;
11837                                                 }
11838                                                 else if (shortest[1].length2 > l || i == 1)
11839                                                 {
11840                                                         shortest[1].length2 = l;
11841                                                         shortest[1].v1 = v1;
11842                                                         shortest[1].v2 = v2;
11843                                                 }
11844                                         }
11845                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11846                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11847                                         // this calculates the right vector from the shortest edge
11848                                         // and the up vector from the edge midpoints
11849                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11850                                         VectorNormalize(right);
11851                                         VectorSubtract(end, start, up);
11852                                         VectorNormalize(up);
11853                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11854                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11855                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11856                                         VectorNegate(forward, forward);
11857                                         VectorReflect(forward, 0, up, forward);
11858                                         VectorNormalize(forward);
11859                                         CrossProduct(up, forward, newright);
11860                                         VectorNormalize(newright);
11861                                         // rotate the quad around the up axis vector, this is made
11862                                         // especially easy by the fact we know the quad is flat,
11863                                         // so we only have to subtract the center position and
11864                                         // measure distance along the right vector, and then
11865                                         // multiply that by the newright vector and add back the
11866                                         // center position
11867                                         // we also need to subtract the old position to undo the
11868                                         // displacement from the center, which we do with a
11869                                         // DotProduct, the subtraction/addition of center is also
11870                                         // optimized into DotProducts here
11871                                         l = DotProduct(right, center);
11872                                         for (i = 0;i < 4;i++)
11873                                         {
11874                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11875                                                 f = DotProduct(right, v1) - l;
11876                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11877                                         }
11878                                 }
11879                         }
11880                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11881                         rsurface.batchvertex3f_vertexbuffer = NULL;
11882                         rsurface.batchvertex3f_bufferoffset = 0;
11883                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11884                         {
11885                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11886                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11887                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11888                                 rsurface.batchnormal3f_bufferoffset = 0;
11889                         }
11890                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11891                         {
11892                                 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);
11893                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11894                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11895                                 rsurface.batchsvector3f_bufferoffset = 0;
11896                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11897                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11898                                 rsurface.batchtvector3f_bufferoffset = 0;
11899                         }
11900                         break;
11901                 case Q3DEFORM_NORMAL:
11902                         // deform the normals to make reflections wavey
11903                         for (j = 0;j < rsurface.batchnumvertices;j++)
11904                         {
11905                                 float vertex[3];
11906                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11907                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11908                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11909                                 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]);
11910                                 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]);
11911                                 VectorNormalize(normal);
11912                         }
11913                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11914                         rsurface.batchnormal3f_vertexbuffer = NULL;
11915                         rsurface.batchnormal3f_bufferoffset = 0;
11916                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11917                         {
11918                                 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);
11919                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11920                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11921                                 rsurface.batchsvector3f_bufferoffset = 0;
11922                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11923                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11924                                 rsurface.batchtvector3f_bufferoffset = 0;
11925                         }
11926                         break;
11927                 case Q3DEFORM_WAVE:
11928                         // deform vertex array to make wavey water and flags and such
11929                         waveparms[0] = deform->waveparms[0];
11930                         waveparms[1] = deform->waveparms[1];
11931                         waveparms[2] = deform->waveparms[2];
11932                         waveparms[3] = deform->waveparms[3];
11933                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11934                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11935                         // this is how a divisor of vertex influence on deformation
11936                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11937                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11938                         for (j = 0;j < rsurface.batchnumvertices;j++)
11939                         {
11940                                 // if the wavefunc depends on time, evaluate it per-vertex
11941                                 if (waveparms[3])
11942                                 {
11943                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11944                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11945                                 }
11946                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11947                         }
11948                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11949                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11950                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11951                         rsurface.batchvertex3f_vertexbuffer = NULL;
11952                         rsurface.batchvertex3f_bufferoffset = 0;
11953                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11954                         rsurface.batchnormal3f_vertexbuffer = NULL;
11955                         rsurface.batchnormal3f_bufferoffset = 0;
11956                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11957                         {
11958                                 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);
11959                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11960                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11961                                 rsurface.batchsvector3f_bufferoffset = 0;
11962                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11963                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11964                                 rsurface.batchtvector3f_bufferoffset = 0;
11965                         }
11966                         break;
11967                 case Q3DEFORM_BULGE:
11968                         // deform vertex array to make the surface have moving bulges
11969                         for (j = 0;j < rsurface.batchnumvertices;j++)
11970                         {
11971                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11972                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11973                         }
11974                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11975                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11976                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11977                         rsurface.batchvertex3f_vertexbuffer = NULL;
11978                         rsurface.batchvertex3f_bufferoffset = 0;
11979                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11980                         rsurface.batchnormal3f_vertexbuffer = NULL;
11981                         rsurface.batchnormal3f_bufferoffset = 0;
11982                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11983                         {
11984                                 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);
11985                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11986                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11987                                 rsurface.batchsvector3f_bufferoffset = 0;
11988                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11989                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11990                                 rsurface.batchtvector3f_bufferoffset = 0;
11991                         }
11992                         break;
11993                 case Q3DEFORM_MOVE:
11994                         // deform vertex array
11995                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11996                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11997                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11998                         VectorScale(deform->parms, scale, waveparms);
11999                         for (j = 0;j < rsurface.batchnumvertices;j++)
12000                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
12001                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
12002                         rsurface.batchvertex3f_vertexbuffer = NULL;
12003                         rsurface.batchvertex3f_bufferoffset = 0;
12004                         break;
12005                 }
12006         }
12007
12008         // generate texcoords based on the chosen texcoord source
12009         switch(rsurface.texture->tcgen.tcgen)
12010         {
12011         default:
12012         case Q3TCGEN_TEXTURE:
12013                 break;
12014         case Q3TCGEN_LIGHTMAP:
12015                 if (rsurface.batchtexcoordlightmap2f)
12016                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
12017                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12018                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12019                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12020                 break;
12021         case Q3TCGEN_VECTOR:
12022                 for (j = 0;j < rsurface.batchnumvertices;j++)
12023                 {
12024                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12025                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12026                 }
12027                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12028                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12029                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12030                 break;
12031         case Q3TCGEN_ENVIRONMENT:
12032                 // make environment reflections using a spheremap
12033                 for (j = 0;j < rsurface.batchnumvertices;j++)
12034                 {
12035                         // identical to Q3A's method, but executed in worldspace so
12036                         // carried models can be shiny too
12037
12038                         float viewer[3], d, reflected[3], worldreflected[3];
12039
12040                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12041                         // VectorNormalize(viewer);
12042
12043                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12044
12045                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12046                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12047                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12048                         // note: this is proportinal to viewer, so we can normalize later
12049
12050                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12051                         VectorNormalize(worldreflected);
12052
12053                         // note: this sphere map only uses world x and z!
12054                         // so positive and negative y will LOOK THE SAME.
12055                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12056                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12057                 }
12058                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12059                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12060                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12061                 break;
12062         }
12063         // the only tcmod that needs software vertex processing is turbulent, so
12064         // check for it here and apply the changes if needed
12065         // and we only support that as the first one
12066         // (handling a mixture of turbulent and other tcmods would be problematic
12067         //  without punting it entirely to a software path)
12068         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12069         {
12070                 amplitude = rsurface.texture->tcmods[0].parms[1];
12071                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12072                 for (j = 0;j < rsurface.batchnumvertices;j++)
12073                 {
12074                         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);
12075                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12076                 }
12077                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
12078                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12079                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12080         }
12081
12082         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12083         {
12084                 // convert the modified arrays to vertex structs
12085                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
12086                 rsurface.batchvertexmeshbuffer = NULL;
12087                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12088                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12089                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12090                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12091                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12092                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12093                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12094                 {
12095                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12096                         {
12097                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12098                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12099                         }
12100                 }
12101                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12102                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12103                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12104                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12105                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12106                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12107                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12108                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
12109                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12110         }
12111
12112         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
12113         {
12114                 // convert the modified arrays to vertex structs
12115                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
12116                 rsurface.batchvertexpositionbuffer = NULL;
12117                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
12118                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
12119                 else
12120                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
12121                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
12122         }
12123 }
12124
12125 void RSurf_DrawBatch(void)
12126 {
12127         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);
12128 }
12129
12130 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12131 {
12132         // pick the closest matching water plane
12133         int planeindex, vertexindex, bestplaneindex = -1;
12134         float d, bestd;
12135         vec3_t vert;
12136         const float *v;
12137         r_waterstate_waterplane_t *p;
12138         bestd = 0;
12139         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12140         {
12141                 if(p->camera_entity != rsurface.texture->camera_entity)
12142                         continue;
12143                 d = 0;
12144                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
12145                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12146                 {
12147                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12148                         d += fabs(PlaneDiff(vert, &p->plane));
12149                 }
12150                 if (bestd > d || bestplaneindex < 0)
12151                 {
12152                         bestd = d;
12153                         bestplaneindex = planeindex;
12154                 }
12155         }
12156         return bestplaneindex;
12157 }
12158
12159 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12160 {
12161         int i;
12162         for (i = 0;i < rsurface.batchnumvertices;i++)
12163                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12164         rsurface.passcolor4f = rsurface.array_passcolor4f;
12165         rsurface.passcolor4f_vertexbuffer = 0;
12166         rsurface.passcolor4f_bufferoffset = 0;
12167 }
12168
12169 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12170 {
12171         int i;
12172         float f;
12173         const float *v;
12174         const float *c;
12175         float *c2;
12176         if (rsurface.passcolor4f)
12177         {
12178                 // generate color arrays
12179                 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)
12180                 {
12181                         f = RSurf_FogVertex(v);
12182                         c2[0] = c[0] * f;
12183                         c2[1] = c[1] * f;
12184                         c2[2] = c[2] * f;
12185                         c2[3] = c[3];
12186                 }
12187         }
12188         else
12189         {
12190                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12191                 {
12192                         f = RSurf_FogVertex(v);
12193                         c2[0] = f;
12194                         c2[1] = f;
12195                         c2[2] = f;
12196                         c2[3] = 1;
12197                 }
12198         }
12199         rsurface.passcolor4f = rsurface.array_passcolor4f;
12200         rsurface.passcolor4f_vertexbuffer = 0;
12201         rsurface.passcolor4f_bufferoffset = 0;
12202 }
12203
12204 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12205 {
12206         int i;
12207         float f;
12208         const float *v;
12209         const float *c;
12210         float *c2;
12211         if (!rsurface.passcolor4f)
12212                 return;
12213         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)
12214         {
12215                 f = RSurf_FogVertex(v);
12216                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12217                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12218                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12219                 c2[3] = c[3];
12220         }
12221         rsurface.passcolor4f = rsurface.array_passcolor4f;
12222         rsurface.passcolor4f_vertexbuffer = 0;
12223         rsurface.passcolor4f_bufferoffset = 0;
12224 }
12225
12226 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12227 {
12228         int i;
12229         const float *c;
12230         float *c2;
12231         if (!rsurface.passcolor4f)
12232                 return;
12233         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12234         {
12235                 c2[0] = c[0] * r;
12236                 c2[1] = c[1] * g;
12237                 c2[2] = c[2] * b;
12238                 c2[3] = c[3] * a;
12239         }
12240         rsurface.passcolor4f = rsurface.array_passcolor4f;
12241         rsurface.passcolor4f_vertexbuffer = 0;
12242         rsurface.passcolor4f_bufferoffset = 0;
12243 }
12244
12245 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12246 {
12247         int i;
12248         const float *c;
12249         float *c2;
12250         if (!rsurface.passcolor4f)
12251                 return;
12252         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12253         {
12254                 c2[0] = c[0] + r_refdef.scene.ambient;
12255                 c2[1] = c[1] + r_refdef.scene.ambient;
12256                 c2[2] = c[2] + r_refdef.scene.ambient;
12257                 c2[3] = c[3];
12258         }
12259         rsurface.passcolor4f = rsurface.array_passcolor4f;
12260         rsurface.passcolor4f_vertexbuffer = 0;
12261         rsurface.passcolor4f_bufferoffset = 0;
12262 }
12263
12264 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12265 {
12266         // TODO: optimize
12267         rsurface.passcolor4f = NULL;
12268         rsurface.passcolor4f_vertexbuffer = 0;
12269         rsurface.passcolor4f_bufferoffset = 0;
12270         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12271         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12272         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12273         GL_Color(r, g, b, a);
12274         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12275         RSurf_DrawBatch();
12276 }
12277
12278 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12279 {
12280         // TODO: optimize applyfog && applycolor case
12281         // just apply fog if necessary, and tint the fog color array if necessary
12282         rsurface.passcolor4f = NULL;
12283         rsurface.passcolor4f_vertexbuffer = 0;
12284         rsurface.passcolor4f_bufferoffset = 0;
12285         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12286         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12287         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12288         GL_Color(r, g, b, a);
12289         RSurf_DrawBatch();
12290 }
12291
12292 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12293 {
12294         // TODO: optimize
12295         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12296         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12297         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12298         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12299         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12300         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12301         GL_Color(r, g, b, a);
12302         RSurf_DrawBatch();
12303 }
12304
12305 static void RSurf_DrawBatch_GL11_ClampColor(void)
12306 {
12307         int i;
12308         const float *c1;
12309         float *c2;
12310         if (!rsurface.passcolor4f)
12311                 return;
12312         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12313         {
12314                 c2[0] = bound(0.0f, c1[0], 1.0f);
12315                 c2[1] = bound(0.0f, c1[1], 1.0f);
12316                 c2[2] = bound(0.0f, c1[2], 1.0f);
12317                 c2[3] = bound(0.0f, c1[3], 1.0f);
12318         }
12319 }
12320
12321 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12322 {
12323         int i;
12324         float f;
12325         float alpha;
12326         const float *v;
12327         const float *n;
12328         float *c;
12329         vec3_t ambientcolor;
12330         vec3_t diffusecolor;
12331         vec3_t lightdir;
12332         // TODO: optimize
12333         // model lighting
12334         VectorCopy(rsurface.modellight_lightdir, lightdir);
12335         f = 0.5f * r_refdef.lightmapintensity;
12336         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12337         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12338         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12339         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12340         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12341         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12342         alpha = *a;
12343         if (VectorLength2(diffusecolor) > 0)
12344         {
12345                 // q3-style directional shading
12346                 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)
12347                 {
12348                         if ((f = DotProduct(n, lightdir)) > 0)
12349                                 VectorMA(ambientcolor, f, diffusecolor, c);
12350                         else
12351                                 VectorCopy(ambientcolor, c);
12352                         c[3] = alpha;
12353                 }
12354                 *r = 1;
12355                 *g = 1;
12356                 *b = 1;
12357                 *a = 1;
12358                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12359                 rsurface.passcolor4f_vertexbuffer = 0;
12360                 rsurface.passcolor4f_bufferoffset = 0;
12361                 *applycolor = false;
12362         }
12363         else
12364         {
12365                 *r = ambientcolor[0];
12366                 *g = ambientcolor[1];
12367                 *b = ambientcolor[2];
12368                 rsurface.passcolor4f = NULL;
12369                 rsurface.passcolor4f_vertexbuffer = 0;
12370                 rsurface.passcolor4f_bufferoffset = 0;
12371         }
12372 }
12373
12374 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12375 {
12376         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12377         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12378         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12379         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12380         GL_Color(r, g, b, a);
12381         RSurf_DrawBatch();
12382 }
12383
12384 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12385 {
12386         int i;
12387         float f;
12388         const float *v;
12389         float *c;
12390         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12391         {
12392                 f = 1 - RSurf_FogVertex(v);
12393                 c[0] = r;
12394                 c[1] = g;
12395                 c[2] = b;
12396                 c[3] = f * a;
12397         }
12398 }
12399
12400 void RSurf_SetupDepthAndCulling(void)
12401 {
12402         // submodels are biased to avoid z-fighting with world surfaces that they
12403         // may be exactly overlapping (avoids z-fighting artifacts on certain
12404         // doors and things in Quake maps)
12405         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12406         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12407         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12408         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12409 }
12410
12411 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12412 {
12413         // transparent sky would be ridiculous
12414         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12415                 return;
12416         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12417         skyrenderlater = true;
12418         RSurf_SetupDepthAndCulling();
12419         GL_DepthMask(true);
12420         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12421         // skymasking on them, and Quake3 never did sky masking (unlike
12422         // software Quake and software Quake2), so disable the sky masking
12423         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12424         // and skymasking also looks very bad when noclipping outside the
12425         // level, so don't use it then either.
12426         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12427         {
12428                 R_Mesh_ResetTextureState();
12429                 if (skyrendermasked)
12430                 {
12431                         R_SetupShader_DepthOrShadow();
12432                         // depth-only (masking)
12433                         GL_ColorMask(0,0,0,0);
12434                         // just to make sure that braindead drivers don't draw
12435                         // anything despite that colormask...
12436                         GL_BlendFunc(GL_ZERO, GL_ONE);
12437                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12438                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12439                 }
12440                 else
12441                 {
12442                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12443                         // fog sky
12444                         GL_BlendFunc(GL_ONE, GL_ZERO);
12445                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12446                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12447                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12448                 }
12449                 RSurf_DrawBatch();
12450                 if (skyrendermasked)
12451                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12452         }
12453         R_Mesh_ResetTextureState();
12454         GL_Color(1, 1, 1, 1);
12455 }
12456
12457 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12458 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12459 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12460 {
12461         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12462                 return;
12463         if (prepass)
12464         {
12465                 // render screenspace normalmap to texture
12466                 GL_DepthMask(true);
12467                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12468                 RSurf_DrawBatch();
12469                 return;
12470         }
12471
12472         // bind lightmap texture
12473
12474         // water/refraction/reflection/camera surfaces have to be handled specially
12475         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12476         {
12477                 int start, end, startplaneindex;
12478                 for (start = 0;start < texturenumsurfaces;start = end)
12479                 {
12480                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12481                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12482                                 ;
12483                         // now that we have a batch using the same planeindex, render it
12484                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12485                         {
12486                                 // render water or distortion background
12487                                 GL_DepthMask(true);
12488                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12489                                 RSurf_DrawBatch();
12490                                 // blend surface on top
12491                                 GL_DepthMask(false);
12492                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12493                                 RSurf_DrawBatch();
12494                         }
12495                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12496                         {
12497                                 // render surface with reflection texture as input
12498                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12499                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
12500                                 RSurf_DrawBatch();
12501                         }
12502                 }
12503                 return;
12504         }
12505
12506         // render surface batch normally
12507         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12508         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12509         RSurf_DrawBatch();
12510 }
12511
12512 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12513 {
12514         // OpenGL 1.3 path - anything not completely ancient
12515         qboolean applycolor;
12516         qboolean applyfog;
12517         int layerindex;
12518         const texturelayer_t *layer;
12519         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);
12520         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12521
12522         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12523         {
12524                 vec4_t layercolor;
12525                 int layertexrgbscale;
12526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12527                 {
12528                         if (layerindex == 0)
12529                                 GL_AlphaTest(true);
12530                         else
12531                         {
12532                                 GL_AlphaTest(false);
12533                                 GL_DepthFunc(GL_EQUAL);
12534                         }
12535                 }
12536                 GL_DepthMask(layer->depthmask && writedepth);
12537                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12538                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12539                 {
12540                         layertexrgbscale = 4;
12541                         VectorScale(layer->color, 0.25f, layercolor);
12542                 }
12543                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12544                 {
12545                         layertexrgbscale = 2;
12546                         VectorScale(layer->color, 0.5f, layercolor);
12547                 }
12548                 else
12549                 {
12550                         layertexrgbscale = 1;
12551                         VectorScale(layer->color, 1.0f, layercolor);
12552                 }
12553                 layercolor[3] = layer->color[3];
12554                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12555                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12556                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12557                 switch (layer->type)
12558                 {
12559                 case TEXTURELAYERTYPE_LITTEXTURE:
12560                         // single-pass lightmapped texture with 2x rgbscale
12561                         R_Mesh_TexBind(0, r_texture_white);
12562                         R_Mesh_TexMatrix(0, NULL);
12563                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12564                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12565                         R_Mesh_TexBind(1, layer->texture);
12566                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12567                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12568                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12569                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12570                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12571                         else if (rsurface.uselightmaptexture)
12572                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12573                         else
12574                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12575                         break;
12576                 case TEXTURELAYERTYPE_TEXTURE:
12577                         // singletexture unlit texture with transparency support
12578                         R_Mesh_TexBind(0, layer->texture);
12579                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12580                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12581                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12582                         R_Mesh_TexBind(1, 0);
12583                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12584                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12585                         break;
12586                 case TEXTURELAYERTYPE_FOG:
12587                         // singletexture fogging
12588                         if (layer->texture)
12589                         {
12590                                 R_Mesh_TexBind(0, layer->texture);
12591                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12592                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12593                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12594                         }
12595                         else
12596                         {
12597                                 R_Mesh_TexBind(0, 0);
12598                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12599                         }
12600                         R_Mesh_TexBind(1, 0);
12601                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12602                         // generate a color array for the fog pass
12603                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12604                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12605                         RSurf_DrawBatch();
12606                         break;
12607                 default:
12608                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12609                 }
12610         }
12611         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12612         {
12613                 GL_DepthFunc(GL_LEQUAL);
12614                 GL_AlphaTest(false);
12615         }
12616 }
12617
12618 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12619 {
12620         // OpenGL 1.1 - crusty old voodoo path
12621         qboolean applyfog;
12622         int layerindex;
12623         const texturelayer_t *layer;
12624         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);
12625         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12626
12627         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12628         {
12629                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12630                 {
12631                         if (layerindex == 0)
12632                                 GL_AlphaTest(true);
12633                         else
12634                         {
12635                                 GL_AlphaTest(false);
12636                                 GL_DepthFunc(GL_EQUAL);
12637                         }
12638                 }
12639                 GL_DepthMask(layer->depthmask && writedepth);
12640                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12641                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12642                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12643                 switch (layer->type)
12644                 {
12645                 case TEXTURELAYERTYPE_LITTEXTURE:
12646                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12647                         {
12648                                 // two-pass lit texture with 2x rgbscale
12649                                 // first the lightmap pass
12650                                 R_Mesh_TexBind(0, r_texture_white);
12651                                 R_Mesh_TexMatrix(0, NULL);
12652                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12653                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12654                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12655                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12656                                 else if (rsurface.uselightmaptexture)
12657                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12658                                 else
12659                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12660                                 // then apply the texture to it
12661                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12662                                 R_Mesh_TexBind(0, layer->texture);
12663                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12664                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12665                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12666                                 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);
12667                         }
12668                         else
12669                         {
12670                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12671                                 R_Mesh_TexBind(0, layer->texture);
12672                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12673                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12674                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12675                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12676                                         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);
12677                                 else
12678                                         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);
12679                         }
12680                         break;
12681                 case TEXTURELAYERTYPE_TEXTURE:
12682                         // singletexture unlit texture with transparency support
12683                         R_Mesh_TexBind(0, layer->texture);
12684                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12685                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12686                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12687                         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);
12688                         break;
12689                 case TEXTURELAYERTYPE_FOG:
12690                         // singletexture fogging
12691                         if (layer->texture)
12692                         {
12693                                 R_Mesh_TexBind(0, layer->texture);
12694                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12695                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12696                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12697                         }
12698                         else
12699                         {
12700                                 R_Mesh_TexBind(0, 0);
12701                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12702                         }
12703                         // generate a color array for the fog pass
12704                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12705                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12706                         RSurf_DrawBatch();
12707                         break;
12708                 default:
12709                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12710                 }
12711         }
12712         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12713         {
12714                 GL_DepthFunc(GL_LEQUAL);
12715                 GL_AlphaTest(false);
12716         }
12717 }
12718
12719 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12720 {
12721         int vi;
12722         int j;
12723         r_vertexgeneric_t *batchvertex;
12724         float c[4];
12725
12726         GL_AlphaTest(false);
12727         R_Mesh_ResetTextureState();
12728         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12729
12730         if(rsurface.texture && rsurface.texture->currentskinframe)
12731         {
12732                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12733                 c[3] *= rsurface.texture->currentalpha;
12734         }
12735         else
12736         {
12737                 c[0] = 1;
12738                 c[1] = 0;
12739                 c[2] = 1;
12740                 c[3] = 1;
12741         }
12742
12743         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12744         {
12745                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12746                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12747                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12748         }
12749
12750         // brighten it up (as texture value 127 means "unlit")
12751         c[0] *= 2 * r_refdef.view.colorscale;
12752         c[1] *= 2 * r_refdef.view.colorscale;
12753         c[2] *= 2 * r_refdef.view.colorscale;
12754
12755         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12756                 c[3] *= r_wateralpha.value;
12757
12758         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12759         {
12760                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12761                 GL_DepthMask(false);
12762         }
12763         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12764         {
12765                 GL_BlendFunc(GL_ONE, GL_ONE);
12766                 GL_DepthMask(false);
12767         }
12768         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12769         {
12770                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12771                 GL_DepthMask(false);
12772         }
12773         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12774         {
12775                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12776                 GL_DepthMask(false);
12777         }
12778         else
12779         {
12780                 GL_BlendFunc(GL_ONE, GL_ZERO);
12781                 GL_DepthMask(writedepth);
12782         }
12783
12784         if (r_showsurfaces.integer == 3)
12785         {
12786                 rsurface.passcolor4f = NULL;
12787
12788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12789                 {
12790                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12791
12792                         rsurface.passcolor4f = NULL;
12793                         rsurface.passcolor4f_vertexbuffer = 0;
12794                         rsurface.passcolor4f_bufferoffset = 0;
12795                 }
12796                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12797                 {
12798                         qboolean applycolor = true;
12799                         float one = 1.0;
12800
12801                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12802
12803                         r_refdef.lightmapintensity = 1;
12804                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12805                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12806                 }
12807                 else
12808                 {
12809                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12810
12811                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12812                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12813                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12814                 }
12815
12816                 if(!rsurface.passcolor4f)
12817                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12818
12819                 RSurf_DrawBatch_GL11_ApplyAmbient();
12820                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12821                 if(r_refdef.fogenabled)
12822                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12823                 RSurf_DrawBatch_GL11_ClampColor();
12824
12825                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12826                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12827                 RSurf_DrawBatch();
12828         }
12829         else if (!r_refdef.view.showdebug)
12830         {
12831                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12832                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12833                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12834                 {
12835                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12836                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12837                 }
12838                 R_Mesh_PrepareVertices_Generic_Unlock();
12839                 RSurf_DrawBatch();
12840         }
12841         else if (r_showsurfaces.integer == 4)
12842         {
12843                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12844                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12845                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12846                 {
12847                         unsigned char c = vi << 3;
12848                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12849                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12850                 }
12851                 R_Mesh_PrepareVertices_Generic_Unlock();
12852                 RSurf_DrawBatch();
12853         }
12854         else if (r_showsurfaces.integer == 2)
12855         {
12856                 const int *e;
12857                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12858                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12859                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12860                 {
12861                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12862                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12863                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12864                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12865                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12866                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12867                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12868                 }
12869                 R_Mesh_PrepareVertices_Generic_Unlock();
12870                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12871         }
12872         else
12873         {
12874                 int texturesurfaceindex;
12875                 int k;
12876                 const msurface_t *surface;
12877                 unsigned char surfacecolor4ub[4];
12878                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12879                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12880                 vi = 0;
12881                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12882                 {
12883                         surface = texturesurfacelist[texturesurfaceindex];
12884                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12885                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12886                         for (j = 0;j < surface->num_vertices;j++)
12887                         {
12888                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12889                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12890                                 vi++;
12891                         }
12892                 }
12893                 R_Mesh_PrepareVertices_Generic_Unlock();
12894                 RSurf_DrawBatch();
12895         }
12896 }
12897
12898 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12899 {
12900         CHECKGLERROR
12901         RSurf_SetupDepthAndCulling();
12902         if (r_showsurfaces.integer)
12903         {
12904                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12905                 return;
12906         }
12907         switch (vid.renderpath)
12908         {
12909         case RENDERPATH_GL20:
12910         case RENDERPATH_CGGL:
12911         case RENDERPATH_D3D9:
12912         case RENDERPATH_D3D10:
12913         case RENDERPATH_D3D11:
12914                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12915                 break;
12916         case RENDERPATH_GL13:
12917                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12918                 break;
12919         case RENDERPATH_GL11:
12920                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12921                 break;
12922         }
12923         CHECKGLERROR
12924 }
12925
12926 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12927 {
12928         CHECKGLERROR
12929         RSurf_SetupDepthAndCulling();
12930         if (r_showsurfaces.integer)
12931         {
12932                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12933                 return;
12934         }
12935         switch (vid.renderpath)
12936         {
12937         case RENDERPATH_GL20:
12938         case RENDERPATH_CGGL:
12939         case RENDERPATH_D3D9:
12940         case RENDERPATH_D3D10:
12941         case RENDERPATH_D3D11:
12942                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12943                 break;
12944         case RENDERPATH_GL13:
12945                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12946                 break;
12947         case RENDERPATH_GL11:
12948                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12949                 break;
12950         }
12951         CHECKGLERROR
12952 }
12953
12954 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12955 {
12956         int i, j;
12957         int texturenumsurfaces, endsurface;
12958         texture_t *texture;
12959         const msurface_t *surface;
12960 #define MAXBATCH_TRANSPARENTSURFACES 256
12961         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12962
12963         // if the model is static it doesn't matter what value we give for
12964         // wantnormals and wanttangents, so this logic uses only rules applicable
12965         // to a model, knowing that they are meaningless otherwise
12966         if (ent == r_refdef.scene.worldentity)
12967                 RSurf_ActiveWorldEntity();
12968         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12969                 RSurf_ActiveModelEntity(ent, false, false, false);
12970         else
12971         {
12972                 switch (vid.renderpath)
12973                 {
12974                 case RENDERPATH_GL20:
12975                 case RENDERPATH_CGGL:
12976                 case RENDERPATH_D3D9:
12977                 case RENDERPATH_D3D10:
12978                 case RENDERPATH_D3D11:
12979                         RSurf_ActiveModelEntity(ent, true, true, false);
12980                         break;
12981                 case RENDERPATH_GL13:
12982                 case RENDERPATH_GL11:
12983                         RSurf_ActiveModelEntity(ent, true, false, false);
12984                         break;
12985                 }
12986         }
12987
12988         if (r_transparentdepthmasking.integer)
12989         {
12990                 qboolean setup = false;
12991                 for (i = 0;i < numsurfaces;i = j)
12992                 {
12993                         j = i + 1;
12994                         surface = rsurface.modelsurfaces + surfacelist[i];
12995                         texture = surface->texture;
12996                         rsurface.texture = R_GetCurrentTexture(texture);
12997                         rsurface.lightmaptexture = NULL;
12998                         rsurface.deluxemaptexture = NULL;
12999                         rsurface.uselightmaptexture = false;
13000                         // scan ahead until we find a different texture
13001                         endsurface = min(i + 1024, numsurfaces);
13002                         texturenumsurfaces = 0;
13003                         texturesurfacelist[texturenumsurfaces++] = surface;
13004                         for (;j < endsurface;j++)
13005                         {
13006                                 surface = rsurface.modelsurfaces + surfacelist[j];
13007                                 if (texture != surface->texture)
13008                                         break;
13009                                 texturesurfacelist[texturenumsurfaces++] = surface;
13010                         }
13011                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13012                                 continue;
13013                         // render the range of surfaces as depth
13014                         if (!setup)
13015                         {
13016                                 setup = true;
13017                                 GL_ColorMask(0,0,0,0);
13018                                 GL_Color(1,1,1,1);
13019                                 GL_DepthTest(true);
13020                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13021                                 GL_DepthMask(true);
13022                                 GL_AlphaTest(false);
13023                                 R_Mesh_ResetTextureState();
13024                                 R_SetupShader_DepthOrShadow();
13025                         }
13026                         RSurf_SetupDepthAndCulling();
13027                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13028                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13029                         RSurf_DrawBatch();
13030                 }
13031                 if (setup)
13032                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13033         }
13034
13035         for (i = 0;i < numsurfaces;i = j)
13036         {
13037                 j = i + 1;
13038                 surface = rsurface.modelsurfaces + surfacelist[i];
13039                 texture = surface->texture;
13040                 rsurface.texture = R_GetCurrentTexture(texture);
13041                 rsurface.lightmaptexture = surface->lightmaptexture;
13042                 rsurface.deluxemaptexture = surface->deluxemaptexture;
13043                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13044                 // scan ahead until we find a different texture
13045                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13046                 texturenumsurfaces = 0;
13047                 texturesurfacelist[texturenumsurfaces++] = surface;
13048                 for (;j < endsurface;j++)
13049                 {
13050                         surface = rsurface.modelsurfaces + surfacelist[j];
13051                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13052                                 break;
13053                         texturesurfacelist[texturenumsurfaces++] = surface;
13054                 }
13055                 // render the range of surfaces
13056                 if (ent == r_refdef.scene.worldentity)
13057                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13058                 else
13059                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13060         }
13061         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13062         GL_AlphaTest(false);
13063 }
13064
13065 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13066 {
13067         // transparent surfaces get pushed off into the transparent queue
13068         int surfacelistindex;
13069         const msurface_t *surface;
13070         vec3_t tempcenter, center;
13071         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13072         {
13073                 surface = texturesurfacelist[surfacelistindex];
13074                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13075                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13076                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13077                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13078                 if (queueentity->transparent_offset) // transparent offset
13079                 {
13080                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13081                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13082                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13083                 }
13084                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13085         }
13086 }
13087
13088 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13089 {
13090         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13091                 return;
13092         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13093                 return;
13094         RSurf_SetupDepthAndCulling();
13095         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
13096         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
13097         RSurf_DrawBatch();
13098 }
13099
13100 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13101 {
13102         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13103         CHECKGLERROR
13104         if (depthonly)
13105                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13106         else if (prepass)
13107         {
13108                 if (!rsurface.texture->currentnumlayers)
13109                         return;
13110                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13111                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13112                 else
13113                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13114         }
13115         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13116                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13117         else if (!rsurface.texture->currentnumlayers)
13118                 return;
13119         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13120         {
13121                 // in the deferred case, transparent surfaces were queued during prepass
13122                 if (!r_shadow_usingdeferredprepass)
13123                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13124         }
13125         else
13126         {
13127                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13128                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13129         }
13130         CHECKGLERROR
13131 }
13132
13133 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13134 {
13135         int i, j;
13136         texture_t *texture;
13137         // break the surface list down into batches by texture and use of lightmapping
13138         for (i = 0;i < numsurfaces;i = j)
13139         {
13140                 j = i + 1;
13141                 // texture is the base texture pointer, rsurface.texture is the
13142                 // current frame/skin the texture is directing us to use (for example
13143                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13144                 // use skin 1 instead)
13145                 texture = surfacelist[i]->texture;
13146                 rsurface.texture = R_GetCurrentTexture(texture);
13147                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13148                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13149                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13150                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13151                 {
13152                         // if this texture is not the kind we want, skip ahead to the next one
13153                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13154                                 ;
13155                         continue;
13156                 }
13157                 // simply scan ahead until we find a different texture or lightmap state
13158                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13159                         ;
13160                 // render the range of surfaces
13161                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13162         }
13163 }
13164
13165 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13166 {
13167         CHECKGLERROR
13168         if (depthonly)
13169                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13170         else if (prepass)
13171         {
13172                 if (!rsurface.texture->currentnumlayers)
13173                         return;
13174                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13175                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13176                 else
13177                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13178         }
13179         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13180                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13181         else if (!rsurface.texture->currentnumlayers)
13182                 return;
13183         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13184         {
13185                 // in the deferred case, transparent surfaces were queued during prepass
13186                 if (!r_shadow_usingdeferredprepass)
13187                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13188         }
13189         else
13190         {
13191                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13192                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13193         }
13194         CHECKGLERROR
13195 }
13196
13197 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13198 {
13199         int i, j;
13200         texture_t *texture;
13201         // break the surface list down into batches by texture and use of lightmapping
13202         for (i = 0;i < numsurfaces;i = j)
13203         {
13204                 j = i + 1;
13205                 // texture is the base texture pointer, rsurface.texture is the
13206                 // current frame/skin the texture is directing us to use (for example
13207                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13208                 // use skin 1 instead)
13209                 texture = surfacelist[i]->texture;
13210                 rsurface.texture = R_GetCurrentTexture(texture);
13211                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13212                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13213                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
13214                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13215                 {
13216                         // if this texture is not the kind we want, skip ahead to the next one
13217                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13218                                 ;
13219                         continue;
13220                 }
13221                 // simply scan ahead until we find a different texture or lightmap state
13222                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13223                         ;
13224                 // render the range of surfaces
13225                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13226         }
13227 }
13228
13229 float locboxvertex3f[6*4*3] =
13230 {
13231         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13232         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13233         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13234         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13235         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13236         1,0,0, 0,0,0, 0,1,0, 1,1,0
13237 };
13238
13239 unsigned short locboxelements[6*2*3] =
13240 {
13241          0, 1, 2, 0, 2, 3,
13242          4, 5, 6, 4, 6, 7,
13243          8, 9,10, 8,10,11,
13244         12,13,14, 12,14,15,
13245         16,17,18, 16,18,19,
13246         20,21,22, 20,22,23
13247 };
13248
13249 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13250 {
13251         int i, j;
13252         cl_locnode_t *loc = (cl_locnode_t *)ent;
13253         vec3_t mins, size;
13254         float vertex3f[6*4*3];
13255         CHECKGLERROR
13256         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13257         GL_DepthMask(false);
13258         GL_DepthRange(0, 1);
13259         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13260         GL_DepthTest(true);
13261         GL_CullFace(GL_NONE);
13262         R_EntityMatrix(&identitymatrix);
13263
13264         R_Mesh_ResetTextureState();
13265
13266         i = surfacelist[0];
13267         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13268                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13269                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13270                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13271
13272         if (VectorCompare(loc->mins, loc->maxs))
13273         {
13274                 VectorSet(size, 2, 2, 2);
13275                 VectorMA(loc->mins, -0.5f, size, mins);
13276         }
13277         else
13278         {
13279                 VectorCopy(loc->mins, mins);
13280                 VectorSubtract(loc->maxs, loc->mins, size);
13281         }
13282
13283         for (i = 0;i < 6*4*3;)
13284                 for (j = 0;j < 3;j++, i++)
13285                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13286
13287         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13288         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13289         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13290 }
13291
13292 void R_DrawLocs(void)
13293 {
13294         int index;
13295         cl_locnode_t *loc, *nearestloc;
13296         vec3_t center;
13297         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13298         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13299         {
13300                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13301                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13302         }
13303 }
13304
13305 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13306 {
13307         if (decalsystem->decals)
13308                 Mem_Free(decalsystem->decals);
13309         memset(decalsystem, 0, sizeof(*decalsystem));
13310 }
13311
13312 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)
13313 {
13314         tridecal_t *decal;
13315         tridecal_t *decals;
13316         int i;
13317
13318         // expand or initialize the system
13319         if (decalsystem->maxdecals <= decalsystem->numdecals)
13320         {
13321                 decalsystem_t old = *decalsystem;
13322                 qboolean useshortelements;
13323                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13324                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13325                 decalsystem->decals = (tridecal_t *)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)));
13326                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13327                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13328                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13329                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13330                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13331                 if (decalsystem->numdecals)
13332                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13333                 if (old.decals)
13334                         Mem_Free(old.decals);
13335                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13336                         decalsystem->element3i[i] = i;
13337                 if (useshortelements)
13338                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13339                                 decalsystem->element3s[i] = i;
13340         }
13341
13342         // grab a decal and search for another free slot for the next one
13343         decals = decalsystem->decals;
13344         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13345         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13346                 ;
13347         decalsystem->freedecal = i;
13348         if (decalsystem->numdecals <= i)
13349                 decalsystem->numdecals = i + 1;
13350
13351         // initialize the decal
13352         decal->lived = 0;
13353         decal->triangleindex = triangleindex;
13354         decal->surfaceindex = surfaceindex;
13355         decal->decalsequence = decalsequence;
13356         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13357         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13358         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13359         decal->color4ub[0][3] = 255;
13360         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13361         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13362         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13363         decal->color4ub[1][3] = 255;
13364         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13365         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13366         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13367         decal->color4ub[2][3] = 255;
13368         decal->vertex3f[0][0] = v0[0];
13369         decal->vertex3f[0][1] = v0[1];
13370         decal->vertex3f[0][2] = v0[2];
13371         decal->vertex3f[1][0] = v1[0];
13372         decal->vertex3f[1][1] = v1[1];
13373         decal->vertex3f[1][2] = v1[2];
13374         decal->vertex3f[2][0] = v2[0];
13375         decal->vertex3f[2][1] = v2[1];
13376         decal->vertex3f[2][2] = v2[2];
13377         decal->texcoord2f[0][0] = t0[0];
13378         decal->texcoord2f[0][1] = t0[1];
13379         decal->texcoord2f[1][0] = t1[0];
13380         decal->texcoord2f[1][1] = t1[1];
13381         decal->texcoord2f[2][0] = t2[0];
13382         decal->texcoord2f[2][1] = t2[1];
13383 }
13384
13385 extern cvar_t cl_decals_bias;
13386 extern cvar_t cl_decals_models;
13387 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13388 // baseparms, parms, temps
13389 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)
13390 {
13391         int cornerindex;
13392         int index;
13393         float v[9][3];
13394         const float *vertex3f;
13395         int numpoints;
13396         float points[2][9][3];
13397         float temp[3];
13398         float tc[9][2];
13399         float f;
13400         float c[9][4];
13401         const int *e;
13402
13403         e = rsurface.modelelement3i + 3*triangleindex;
13404
13405         vertex3f = rsurface.modelvertex3f;
13406
13407         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13408         {
13409                 index = 3*e[cornerindex];
13410                 VectorCopy(vertex3f + index, v[cornerindex]);
13411         }
13412         // cull backfaces
13413         //TriangleNormal(v[0], v[1], v[2], normal);
13414         //if (DotProduct(normal, localnormal) < 0.0f)
13415         //      continue;
13416         // clip by each of the box planes formed from the projection matrix
13417         // if anything survives, we emit the decal
13418         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]);
13419         if (numpoints < 3)
13420                 return;
13421         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]);
13422         if (numpoints < 3)
13423                 return;
13424         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]);
13425         if (numpoints < 3)
13426                 return;
13427         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]);
13428         if (numpoints < 3)
13429                 return;
13430         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]);
13431         if (numpoints < 3)
13432                 return;
13433         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]);
13434         if (numpoints < 3)
13435                 return;
13436         // some part of the triangle survived, so we have to accept it...
13437         if (dynamic)
13438         {
13439                 // dynamic always uses the original triangle
13440                 numpoints = 3;
13441                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13442                 {
13443                         index = 3*e[cornerindex];
13444                         VectorCopy(vertex3f + index, v[cornerindex]);
13445                 }
13446         }
13447         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13448         {
13449                 // convert vertex positions to texcoords
13450                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13451                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13452                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13453                 // calculate distance fade from the projection origin
13454                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13455                 f = bound(0.0f, f, 1.0f);
13456                 c[cornerindex][0] = r * f;
13457                 c[cornerindex][1] = g * f;
13458                 c[cornerindex][2] = b * f;
13459                 c[cornerindex][3] = 1.0f;
13460                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13461         }
13462         if (dynamic)
13463                 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);
13464         else
13465                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13466                         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);
13467 }
13468 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)
13469 {
13470         matrix4x4_t projection;
13471         decalsystem_t *decalsystem;
13472         qboolean dynamic;
13473         dp_model_t *model;
13474         const msurface_t *surface;
13475         const msurface_t *surfaces;
13476         const int *surfacelist;
13477         const texture_t *texture;
13478         int numtriangles;
13479         int numsurfacelist;
13480         int surfacelistindex;
13481         int surfaceindex;
13482         int triangleindex;
13483         float localorigin[3];
13484         float localnormal[3];
13485         float localmins[3];
13486         float localmaxs[3];
13487         float localsize;
13488         //float normal[3];
13489         float planes[6][4];
13490         float angles[3];
13491         bih_t *bih;
13492         int bih_triangles_count;
13493         int bih_triangles[256];
13494         int bih_surfaces[256];
13495
13496         decalsystem = &ent->decalsystem;
13497         model = ent->model;
13498         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13499         {
13500                 R_DecalSystem_Reset(&ent->decalsystem);
13501                 return;
13502         }
13503
13504         if (!model->brush.data_leafs && !cl_decals_models.integer)
13505         {
13506                 if (decalsystem->model)
13507                         R_DecalSystem_Reset(decalsystem);
13508                 return;
13509         }
13510
13511         if (decalsystem->model != model)
13512                 R_DecalSystem_Reset(decalsystem);
13513         decalsystem->model = model;
13514
13515         RSurf_ActiveModelEntity(ent, false, false, false);
13516
13517         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13518         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13519         VectorNormalize(localnormal);
13520         localsize = worldsize*rsurface.inversematrixscale;
13521         localmins[0] = localorigin[0] - localsize;
13522         localmins[1] = localorigin[1] - localsize;
13523         localmins[2] = localorigin[2] - localsize;
13524         localmaxs[0] = localorigin[0] + localsize;
13525         localmaxs[1] = localorigin[1] + localsize;
13526         localmaxs[2] = localorigin[2] + localsize;
13527
13528         //VectorCopy(localnormal, planes[4]);
13529         //VectorVectors(planes[4], planes[2], planes[0]);
13530         AnglesFromVectors(angles, localnormal, NULL, false);
13531         AngleVectors(angles, planes[0], planes[2], planes[4]);
13532         VectorNegate(planes[0], planes[1]);
13533         VectorNegate(planes[2], planes[3]);
13534         VectorNegate(planes[4], planes[5]);
13535         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13536         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13537         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13538         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13539         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13540         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13541
13542 #if 1
13543 // works
13544 {
13545         matrix4x4_t forwardprojection;
13546         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13547         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13548 }
13549 #else
13550 // broken
13551 {
13552         float projectionvector[4][3];
13553         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13554         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13555         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13556         projectionvector[0][0] = planes[0][0] * ilocalsize;
13557         projectionvector[0][1] = planes[1][0] * ilocalsize;
13558         projectionvector[0][2] = planes[2][0] * ilocalsize;
13559         projectionvector[1][0] = planes[0][1] * ilocalsize;
13560         projectionvector[1][1] = planes[1][1] * ilocalsize;
13561         projectionvector[1][2] = planes[2][1] * ilocalsize;
13562         projectionvector[2][0] = planes[0][2] * ilocalsize;
13563         projectionvector[2][1] = planes[1][2] * ilocalsize;
13564         projectionvector[2][2] = planes[2][2] * ilocalsize;
13565         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13566         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13567         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13568         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13569 }
13570 #endif
13571
13572         dynamic = model->surfmesh.isanimated;
13573         numsurfacelist = model->nummodelsurfaces;
13574         surfacelist = model->sortedmodelsurfaces;
13575         surfaces = model->data_surfaces;
13576
13577         bih = NULL;
13578         bih_triangles_count = -1;
13579         if(!dynamic)
13580         {
13581                 if(model->render_bih.numleafs)
13582                         bih = &model->render_bih;
13583                 else if(model->collision_bih.numleafs)
13584                         bih = &model->collision_bih;
13585         }
13586         if(bih)
13587                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13588         if(bih_triangles_count == 0)
13589                 return;
13590         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13591                 return;
13592         if(bih_triangles_count > 0)
13593         {
13594                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13595                 {
13596                         surfaceindex = bih_surfaces[triangleindex];
13597                         surface = surfaces + surfaceindex;
13598                         texture = surface->texture;
13599                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13600                                 continue;
13601                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13602                                 continue;
13603                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13604                 }
13605         }
13606         else
13607         {
13608                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13609                 {
13610                         surfaceindex = surfacelist[surfacelistindex];
13611                         surface = surfaces + surfaceindex;
13612                         // check cull box first because it rejects more than any other check
13613                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13614                                 continue;
13615                         // skip transparent surfaces
13616                         texture = surface->texture;
13617                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13618                                 continue;
13619                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13620                                 continue;
13621                         numtriangles = surface->num_triangles;
13622                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13623                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13624                 }
13625         }
13626 }
13627
13628 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13629 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)
13630 {
13631         int renderentityindex;
13632         float worldmins[3];
13633         float worldmaxs[3];
13634         entity_render_t *ent;
13635
13636         if (!cl_decals_newsystem.integer)
13637                 return;
13638
13639         worldmins[0] = worldorigin[0] - worldsize;
13640         worldmins[1] = worldorigin[1] - worldsize;
13641         worldmins[2] = worldorigin[2] - worldsize;
13642         worldmaxs[0] = worldorigin[0] + worldsize;
13643         worldmaxs[1] = worldorigin[1] + worldsize;
13644         worldmaxs[2] = worldorigin[2] + worldsize;
13645
13646         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13647
13648         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13649         {
13650                 ent = r_refdef.scene.entities[renderentityindex];
13651                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13652                         continue;
13653
13654                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13655         }
13656 }
13657
13658 typedef struct r_decalsystem_splatqueue_s
13659 {
13660         vec3_t worldorigin;
13661         vec3_t worldnormal;
13662         float color[4];
13663         float tcrange[4];
13664         float worldsize;
13665         int decalsequence;
13666 }
13667 r_decalsystem_splatqueue_t;
13668
13669 int r_decalsystem_numqueued = 0;
13670 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13671
13672 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)
13673 {
13674         r_decalsystem_splatqueue_t *queue;
13675
13676         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13677                 return;
13678
13679         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13680         VectorCopy(worldorigin, queue->worldorigin);
13681         VectorCopy(worldnormal, queue->worldnormal);
13682         Vector4Set(queue->color, r, g, b, a);
13683         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13684         queue->worldsize = worldsize;
13685         queue->decalsequence = cl.decalsequence++;
13686 }
13687
13688 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13689 {
13690         int i;
13691         r_decalsystem_splatqueue_t *queue;
13692
13693         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13694                 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);
13695         r_decalsystem_numqueued = 0;
13696 }
13697
13698 extern cvar_t cl_decals_max;
13699 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13700 {
13701         int i;
13702         decalsystem_t *decalsystem = &ent->decalsystem;
13703         int numdecals;
13704         int killsequence;
13705         tridecal_t *decal;
13706         float frametime;
13707         float lifetime;
13708
13709         if (!decalsystem->numdecals)
13710                 return;
13711
13712         if (r_showsurfaces.integer)
13713                 return;
13714
13715         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13716         {
13717                 R_DecalSystem_Reset(decalsystem);
13718                 return;
13719         }
13720
13721         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13722         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13723
13724         if (decalsystem->lastupdatetime)
13725                 frametime = (cl.time - decalsystem->lastupdatetime);
13726         else
13727                 frametime = 0;
13728         decalsystem->lastupdatetime = cl.time;
13729         decal = decalsystem->decals;
13730         numdecals = decalsystem->numdecals;
13731
13732         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13733         {
13734                 if (decal->color4ub[0][3])
13735                 {
13736                         decal->lived += frametime;
13737                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13738                         {
13739                                 memset(decal, 0, sizeof(*decal));
13740                                 if (decalsystem->freedecal > i)
13741                                         decalsystem->freedecal = i;
13742                         }
13743                 }
13744         }
13745         decal = decalsystem->decals;
13746         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13747                 numdecals--;
13748
13749         // collapse the array by shuffling the tail decals into the gaps
13750         for (;;)
13751         {
13752                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13753                         decalsystem->freedecal++;
13754                 if (decalsystem->freedecal == numdecals)
13755                         break;
13756                 decal[decalsystem->freedecal] = decal[--numdecals];
13757         }
13758
13759         decalsystem->numdecals = numdecals;
13760
13761         if (numdecals <= 0)
13762         {
13763                 // if there are no decals left, reset decalsystem
13764                 R_DecalSystem_Reset(decalsystem);
13765         }
13766 }
13767
13768 extern skinframe_t *decalskinframe;
13769 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13770 {
13771         int i;
13772         decalsystem_t *decalsystem = &ent->decalsystem;
13773         int numdecals;
13774         tridecal_t *decal;
13775         float faderate;
13776         float alpha;
13777         float *v3f;
13778         float *c4f;
13779         float *t2f;
13780         const int *e;
13781         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13782         int numtris = 0;
13783
13784         numdecals = decalsystem->numdecals;
13785         if (!numdecals)
13786                 return;
13787
13788         if (r_showsurfaces.integer)
13789                 return;
13790
13791         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13792         {
13793                 R_DecalSystem_Reset(decalsystem);
13794                 return;
13795         }
13796
13797         // if the model is static it doesn't matter what value we give for
13798         // wantnormals and wanttangents, so this logic uses only rules applicable
13799         // to a model, knowing that they are meaningless otherwise
13800         if (ent == r_refdef.scene.worldentity)
13801                 RSurf_ActiveWorldEntity();
13802         else
13803                 RSurf_ActiveModelEntity(ent, false, false, false);
13804
13805         decalsystem->lastupdatetime = cl.time;
13806         decal = decalsystem->decals;
13807
13808         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13809
13810         // update vertex positions for animated models
13811         v3f = decalsystem->vertex3f;
13812         c4f = decalsystem->color4f;
13813         t2f = decalsystem->texcoord2f;
13814         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13815         {
13816                 if (!decal->color4ub[0][3])
13817                         continue;
13818
13819                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13820                         continue;
13821
13822                 // update color values for fading decals
13823                 if (decal->lived >= cl_decals_time.value)
13824                 {
13825                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13826                         alpha *= (1.0f/255.0f);
13827                 }
13828                 else
13829                         alpha = 1.0f/255.0f;
13830
13831                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13832                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13833                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13834                 c4f[ 3] = 1;
13835                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13836                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13837                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13838                 c4f[ 7] = 1;
13839                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13840                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13841                 c4f[10] = decal->color4ub[2][2] * alpha;
13842                 c4f[11] = 1;
13843
13844                 t2f[0] = decal->texcoord2f[0][0];
13845                 t2f[1] = decal->texcoord2f[0][1];
13846                 t2f[2] = decal->texcoord2f[1][0];
13847                 t2f[3] = decal->texcoord2f[1][1];
13848                 t2f[4] = decal->texcoord2f[2][0];
13849                 t2f[5] = decal->texcoord2f[2][1];
13850
13851                 // update vertex positions for animated models
13852                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13853                 {
13854                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13855                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13856                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13857                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13858                 }
13859                 else
13860                 {
13861                         VectorCopy(decal->vertex3f[0], v3f);
13862                         VectorCopy(decal->vertex3f[1], v3f + 3);
13863                         VectorCopy(decal->vertex3f[2], v3f + 6);
13864                 }
13865
13866                 if (r_refdef.fogenabled)
13867                 {
13868                         alpha = RSurf_FogVertex(v3f);
13869                         VectorScale(c4f, alpha, c4f);
13870                         alpha = RSurf_FogVertex(v3f + 3);
13871                         VectorScale(c4f + 4, alpha, c4f + 4);
13872                         alpha = RSurf_FogVertex(v3f + 6);
13873                         VectorScale(c4f + 8, alpha, c4f + 8);
13874                 }
13875
13876                 v3f += 9;
13877                 c4f += 12;
13878                 t2f += 6;
13879                 numtris++;
13880         }
13881
13882         if (numtris > 0)
13883         {
13884                 r_refdef.stats.drawndecals += numtris;
13885
13886                 // now render the decals all at once
13887                 // (this assumes they all use one particle font texture!)
13888                 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);
13889                 R_Mesh_ResetTextureState();
13890                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13891                 GL_DepthMask(false);
13892                 GL_DepthRange(0, 1);
13893                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13894                 GL_DepthTest(true);
13895                 GL_CullFace(GL_NONE);
13896                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13897                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13898                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13899         }
13900 }
13901
13902 static void R_DrawModelDecals(void)
13903 {
13904         int i, numdecals;
13905
13906         // fade faster when there are too many decals
13907         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13908         for (i = 0;i < r_refdef.scene.numentities;i++)
13909                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13910
13911         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13912         for (i = 0;i < r_refdef.scene.numentities;i++)
13913                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13914                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13915
13916         R_DecalSystem_ApplySplatEntitiesQueue();
13917
13918         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13919         for (i = 0;i < r_refdef.scene.numentities;i++)
13920                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13921
13922         r_refdef.stats.totaldecals += numdecals;
13923
13924         if (r_showsurfaces.integer)
13925                 return;
13926
13927         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13928
13929         for (i = 0;i < r_refdef.scene.numentities;i++)
13930         {
13931                 if (!r_refdef.viewcache.entityvisible[i])
13932                         continue;
13933                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13934                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13935         }
13936 }
13937
13938 extern cvar_t mod_collision_bih;
13939 void R_DrawDebugModel(void)
13940 {
13941         entity_render_t *ent = rsurface.entity;
13942         int i, j, k, l, flagsmask;
13943         const msurface_t *surface;
13944         dp_model_t *model = ent->model;
13945         vec3_t v;
13946
13947         switch(vid.renderpath)
13948         {
13949         case RENDERPATH_GL11:
13950         case RENDERPATH_GL13:
13951         case RENDERPATH_GL20:
13952         case RENDERPATH_CGGL:
13953                 break;
13954         case RENDERPATH_D3D9:
13955                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13956                 return;
13957         case RENDERPATH_D3D10:
13958                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13959                 return;
13960         case RENDERPATH_D3D11:
13961                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13962                 return;
13963         }
13964
13965         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13966
13967         R_Mesh_ResetTextureState();
13968         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13969         GL_DepthRange(0, 1);
13970         GL_DepthTest(!r_showdisabledepthtest.integer);
13971         GL_DepthMask(false);
13972         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13973
13974         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13975         {
13976                 int triangleindex;
13977                 int bihleafindex;
13978                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13979                 const q3mbrush_t *brush;
13980                 const bih_t *bih = &model->collision_bih;
13981                 const bih_leaf_t *bihleaf;
13982                 float vertex3f[3][3];
13983                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13984                 cullbox = false;
13985                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13986                 {
13987                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13988                                 continue;
13989                         switch (bihleaf->type)
13990                         {
13991                         case BIH_BRUSH:
13992                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13993                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13994                                 {
13995                                         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);
13996                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13997                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13998                                 }
13999                                 break;
14000                         case BIH_COLLISIONTRIANGLE:
14001                                 triangleindex = bihleaf->itemindex;
14002                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14003                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14004                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14005                                 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);
14006                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14007                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14008                                 break;
14009                         case BIH_RENDERTRIANGLE:
14010                                 triangleindex = bihleaf->itemindex;
14011                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14012                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14013                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14014                                 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);
14015                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14016                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14017                                 break;
14018                         }
14019                 }
14020         }
14021
14022         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14023
14024         if (r_showtris.integer || r_shownormals.integer)
14025         {
14026                 if (r_showdisabledepthtest.integer)
14027                 {
14028                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14029                         GL_DepthMask(false);
14030                 }
14031                 else
14032                 {
14033                         GL_BlendFunc(GL_ONE, GL_ZERO);
14034                         GL_DepthMask(true);
14035                 }
14036                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14037                 {
14038                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14039                                 continue;
14040                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14041                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14042                         {
14043                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14044                                 if (r_showtris.value > 0)
14045                                 {
14046                                         if (!rsurface.texture->currentlayers->depthmask)
14047                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14048                                         else if (ent == r_refdef.scene.worldentity)
14049                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14050                                         else
14051                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14052                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14053                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14054                                         RSurf_DrawBatch();
14055                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14056                                         CHECKGLERROR
14057                                 }
14058                                 if (r_shownormals.value < 0)
14059                                 {
14060                                         qglBegin(GL_LINES);
14061                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14062                                         {
14063                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14064                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14065                                                 qglVertex3f(v[0], v[1], v[2]);
14066                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14067                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14068                                                 qglVertex3f(v[0], v[1], v[2]);
14069                                         }
14070                                         qglEnd();
14071                                         CHECKGLERROR
14072                                 }
14073                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14074                                 {
14075                                         qglBegin(GL_LINES);
14076                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14077                                         {
14078                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14079                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14080                                                 qglVertex3f(v[0], v[1], v[2]);
14081                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14082                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14083                                                 qglVertex3f(v[0], v[1], v[2]);
14084                                         }
14085                                         qglEnd();
14086                                         CHECKGLERROR
14087                                         qglBegin(GL_LINES);
14088                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14089                                         {
14090                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14091                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14092                                                 qglVertex3f(v[0], v[1], v[2]);
14093                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14094                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14095                                                 qglVertex3f(v[0], v[1], v[2]);
14096                                         }
14097                                         qglEnd();
14098                                         CHECKGLERROR
14099                                         qglBegin(GL_LINES);
14100                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
14101                                         {
14102                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14103                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14104                                                 qglVertex3f(v[0], v[1], v[2]);
14105                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14106                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
14107                                                 qglVertex3f(v[0], v[1], v[2]);
14108                                         }
14109                                         qglEnd();
14110                                         CHECKGLERROR
14111                                 }
14112                         }
14113                 }
14114                 rsurface.texture = NULL;
14115         }
14116 }
14117
14118 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14119 int r_maxsurfacelist = 0;
14120 const msurface_t **r_surfacelist = NULL;
14121 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14122 {
14123         int i, j, endj, flagsmask;
14124         dp_model_t *model = r_refdef.scene.worldmodel;
14125         msurface_t *surfaces;
14126         unsigned char *update;
14127         int numsurfacelist = 0;
14128         if (model == NULL)
14129                 return;
14130
14131         if (r_maxsurfacelist < model->num_surfaces)
14132         {
14133                 r_maxsurfacelist = model->num_surfaces;
14134                 if (r_surfacelist)
14135                         Mem_Free((msurface_t**)r_surfacelist);
14136                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14137         }
14138
14139         RSurf_ActiveWorldEntity();
14140
14141         surfaces = model->data_surfaces;
14142         update = model->brushq1.lightmapupdateflags;
14143
14144         // update light styles on this submodel
14145         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14146         {
14147                 model_brush_lightstyleinfo_t *style;
14148                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14149                 {
14150                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14151                         {
14152                                 int *list = style->surfacelist;
14153                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14154                                 for (j = 0;j < style->numsurfaces;j++)
14155                                         update[list[j]] = true;
14156                         }
14157                 }
14158         }
14159
14160         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14161
14162         if (debug)
14163         {
14164                 R_DrawDebugModel();
14165                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14166                 return;
14167         }
14168
14169         rsurface.lightmaptexture = NULL;
14170         rsurface.deluxemaptexture = NULL;
14171         rsurface.uselightmaptexture = false;
14172         rsurface.texture = NULL;
14173         rsurface.rtlight = NULL;
14174         numsurfacelist = 0;
14175         // add visible surfaces to draw list
14176         for (i = 0;i < model->nummodelsurfaces;i++)
14177         {
14178                 j = model->sortedmodelsurfaces[i];
14179                 if (r_refdef.viewcache.world_surfacevisible[j])
14180                         r_surfacelist[numsurfacelist++] = surfaces + j;
14181         }
14182         // update lightmaps if needed
14183         if (model->brushq1.firstrender)
14184         {
14185                 model->brushq1.firstrender = false;
14186                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14187                         if (update[j])
14188                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14189         }
14190         else if (update)
14191         {
14192                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14193                         if (r_refdef.viewcache.world_surfacevisible[j])
14194                                 if (update[j])
14195                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14196         }
14197         // don't do anything if there were no surfaces
14198         if (!numsurfacelist)
14199         {
14200                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14201                 return;
14202         }
14203         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14204         GL_AlphaTest(false);
14205
14206         // add to stats if desired
14207         if (r_speeds.integer && !skysurfaces && !depthonly)
14208         {
14209                 r_refdef.stats.world_surfaces += numsurfacelist;
14210                 for (j = 0;j < numsurfacelist;j++)
14211                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14212         }
14213
14214         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14215 }
14216
14217 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14218 {
14219         int i, j, endj, flagsmask;
14220         dp_model_t *model = ent->model;
14221         msurface_t *surfaces;
14222         unsigned char *update;
14223         int numsurfacelist = 0;
14224         if (model == NULL)
14225                 return;
14226
14227         if (r_maxsurfacelist < model->num_surfaces)
14228         {
14229                 r_maxsurfacelist = model->num_surfaces;
14230                 if (r_surfacelist)
14231                         Mem_Free((msurface_t **)r_surfacelist);
14232                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14233         }
14234
14235         // if the model is static it doesn't matter what value we give for
14236         // wantnormals and wanttangents, so this logic uses only rules applicable
14237         // to a model, knowing that they are meaningless otherwise
14238         if (ent == r_refdef.scene.worldentity)
14239                 RSurf_ActiveWorldEntity();
14240         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14241                 RSurf_ActiveModelEntity(ent, false, false, false);
14242         else if (prepass)
14243                 RSurf_ActiveModelEntity(ent, true, true, true);
14244         else if (depthonly)
14245         {
14246                 switch (vid.renderpath)
14247                 {
14248                 case RENDERPATH_GL20:
14249                 case RENDERPATH_CGGL:
14250                 case RENDERPATH_D3D9:
14251                 case RENDERPATH_D3D10:
14252                 case RENDERPATH_D3D11:
14253                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14254                         break;
14255                 case RENDERPATH_GL13:
14256                 case RENDERPATH_GL11:
14257                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14258                         break;
14259                 }
14260         }
14261         else
14262         {
14263                 switch (vid.renderpath)
14264                 {
14265                 case RENDERPATH_GL20:
14266                 case RENDERPATH_CGGL:
14267                 case RENDERPATH_D3D9:
14268                 case RENDERPATH_D3D10:
14269                 case RENDERPATH_D3D11:
14270                         RSurf_ActiveModelEntity(ent, true, true, false);
14271                         break;
14272                 case RENDERPATH_GL13:
14273                 case RENDERPATH_GL11:
14274                         RSurf_ActiveModelEntity(ent, true, false, false);
14275                         break;
14276                 }
14277         }
14278
14279         surfaces = model->data_surfaces;
14280         update = model->brushq1.lightmapupdateflags;
14281
14282         // update light styles
14283         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14284         {
14285                 model_brush_lightstyleinfo_t *style;
14286                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14287                 {
14288                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14289                         {
14290                                 int *list = style->surfacelist;
14291                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14292                                 for (j = 0;j < style->numsurfaces;j++)
14293                                         update[list[j]] = true;
14294                         }
14295                 }
14296         }
14297
14298         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14299
14300         if (debug)
14301         {
14302                 R_DrawDebugModel();
14303                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14304                 return;
14305         }
14306
14307         rsurface.lightmaptexture = NULL;
14308         rsurface.deluxemaptexture = NULL;
14309         rsurface.uselightmaptexture = false;
14310         rsurface.texture = NULL;
14311         rsurface.rtlight = NULL;
14312         numsurfacelist = 0;
14313         // add visible surfaces to draw list
14314         for (i = 0;i < model->nummodelsurfaces;i++)
14315                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14316         // don't do anything if there were no surfaces
14317         if (!numsurfacelist)
14318         {
14319                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14320                 return;
14321         }
14322         // update lightmaps if needed
14323         if (update)
14324         {
14325                 int updated = 0;
14326                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14327                 {
14328                         if (update[j])
14329                         {
14330                                 updated++;
14331                                 R_BuildLightMap(ent, surfaces + j);
14332                         }
14333                 }
14334         }
14335         if (update)
14336                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14337                         if (update[j])
14338                                 R_BuildLightMap(ent, surfaces + j);
14339         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14340         GL_AlphaTest(false);
14341
14342         // add to stats if desired
14343         if (r_speeds.integer && !skysurfaces && !depthonly)
14344         {
14345                 r_refdef.stats.entities_surfaces += numsurfacelist;
14346                 for (j = 0;j < numsurfacelist;j++)
14347                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14348         }
14349
14350         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14351 }
14352
14353 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14354 {
14355         static texture_t texture;
14356         static msurface_t surface;
14357         const msurface_t *surfacelist = &surface;
14358
14359         // fake enough texture and surface state to render this geometry
14360
14361         texture.update_lastrenderframe = -1; // regenerate this texture
14362         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14363         texture.currentskinframe = skinframe;
14364         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14365         texture.offsetmapping = OFFSETMAPPING_OFF;
14366         texture.offsetscale = 1;
14367         texture.specularscalemod = 1;
14368         texture.specularpowermod = 1;
14369
14370         surface.texture = &texture;
14371         surface.num_triangles = numtriangles;
14372         surface.num_firsttriangle = firsttriangle;
14373         surface.num_vertices = numvertices;
14374         surface.num_firstvertex = firstvertex;
14375
14376         // now render it
14377         rsurface.texture = R_GetCurrentTexture(surface.texture);
14378         rsurface.lightmaptexture = NULL;
14379         rsurface.deluxemaptexture = NULL;
14380         rsurface.uselightmaptexture = false;
14381         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14382 }
14383
14384 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)
14385 {
14386         static msurface_t surface;
14387         const msurface_t *surfacelist = &surface;
14388
14389         // fake enough texture and surface state to render this geometry
14390
14391         surface.texture = texture;
14392         surface.num_triangles = numtriangles;
14393         surface.num_firsttriangle = firsttriangle;
14394         surface.num_vertices = numvertices;
14395         surface.num_firstvertex = firstvertex;
14396
14397         // now render it
14398         rsurface.texture = R_GetCurrentTexture(surface.texture);
14399         rsurface.lightmaptexture = NULL;
14400         rsurface.deluxemaptexture = NULL;
14401         rsurface.uselightmaptexture = false;
14402         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14403 }