]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_rmain.c
enable Tomaz's PIX-friendly shader debugging code if gl_paranoid is 1
[divverent/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30
31 #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 "#ifdef USESHADOWMAP2D\n"
591 "# ifdef GL_EXT_gpu_shader4\n"
592 "#   extension GL_EXT_gpu_shader4 : enable\n"
593 "# endif\n"
594 "# ifdef GL_ARB_texture_gather\n"
595 "#   extension GL_ARB_texture_gather : enable\n"
596 "# else\n"
597 "#   ifdef GL_AMD_texture_texture4\n"
598 "#     extension GL_AMD_texture_texture4 : enable\n"
599 "#   endif\n"
600 "# endif\n"
601 "#endif\n"
602 "\n"
603 "//#ifdef USESHADOWSAMPLER\n"
604 "//# extension GL_ARB_shadow : enable\n"
605 "//#endif\n"
606 "\n"
607 "//#ifdef __GLSL_CG_DATA_TYPES\n"
608 "//# define myhalf half\n"
609 "//# define myhalf2 half2\n"
610 "//# define myhalf3 half3\n"
611 "//# define myhalf4 half4\n"
612 "//#else\n"
613 "# define myhalf float\n"
614 "# define myhalf2 vec2\n"
615 "# define myhalf3 vec3\n"
616 "# define myhalf4 vec4\n"
617 "//#endif\n"
618 "\n"
619 "#ifdef VERTEX_SHADER\n"
620 "uniform mat4 ModelViewProjectionMatrix;\n"
621 "#endif\n"
622 "\n"
623 "#ifdef MODE_DEPTH_OR_SHADOW\n"
624 "#ifdef VERTEX_SHADER\n"
625 "void main(void)\n"
626 "{\n"
627 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
628 "}\n"
629 "#endif\n"
630 "#else // !MODE_DEPTH_ORSHADOW\n"
631 "\n"
632 "\n"
633 "\n"
634 "\n"
635 "#ifdef MODE_SHOWDEPTH\n"
636 "#ifdef VERTEX_SHADER\n"
637 "void main(void)\n"
638 "{\n"
639 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
640 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
641 "}\n"
642 "#endif\n"
643 "\n"
644 "#ifdef FRAGMENT_SHADER\n"
645 "void main(void)\n"
646 "{\n"
647 "       gl_FragColor = gl_Color;\n"
648 "}\n"
649 "#endif\n"
650 "#else // !MODE_SHOWDEPTH\n"
651 "\n"
652 "\n"
653 "\n"
654 "\n"
655 "#ifdef MODE_POSTPROCESS\n"
656 "varying vec2 TexCoord1;\n"
657 "varying vec2 TexCoord2;\n"
658 "\n"
659 "#ifdef VERTEX_SHADER\n"
660 "void main(void)\n"
661 "{\n"
662 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
663 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
664 "#ifdef USEBLOOM\n"
665 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
666 "#endif\n"
667 "}\n"
668 "#endif\n"
669 "\n"
670 "#ifdef FRAGMENT_SHADER\n"
671 "uniform sampler2D Texture_First;\n"
672 "#ifdef USEBLOOM\n"
673 "uniform sampler2D Texture_Second;\n"
674 "uniform vec4 BloomColorSubtract;\n"
675 "#endif\n"
676 "#ifdef USEGAMMARAMPS\n"
677 "uniform sampler2D Texture_GammaRamps;\n"
678 "#endif\n"
679 "#ifdef USESATURATION\n"
680 "uniform float Saturation;\n"
681 "#endif\n"
682 "#ifdef USEVIEWTINT\n"
683 "uniform vec4 ViewTintColor;\n"
684 "#endif\n"
685 "//uncomment these if you want to use them:\n"
686 "uniform vec4 UserVec1;\n"
687 "uniform vec4 UserVec2;\n"
688 "// uniform vec4 UserVec3;\n"
689 "// uniform vec4 UserVec4;\n"
690 "// uniform float ClientTime;\n"
691 "uniform vec2 PixelSize;\n"
692 "void main(void)\n"
693 "{\n"
694 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
695 "#ifdef USEBLOOM\n"
696 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
697 "#endif\n"
698 "#ifdef USEVIEWTINT\n"
699 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
700 "#endif\n"
701 "\n"
702 "#ifdef USEPOSTPROCESSING\n"
703 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
704 "// 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"
705 "       float sobel = 1.0;\n"
706 "       // vec2 ts = textureSize(Texture_First, 0);\n"
707 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
708 "       vec2 px = PixelSize;\n"
709 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
710 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
711 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
712 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
713 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
714 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
715 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
716 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
717 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
718 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
719 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
720 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
721 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
722 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
723 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
724 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
725 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
726 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
727 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
728 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
729 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
730 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
731 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
732 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
733 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
734 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
735 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
736 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
737 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
738 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
739 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
740 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
741 "#endif\n"
742 "\n"
743 "#ifdef USESATURATION\n"
744 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
745 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
746 "       //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
747 "       gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
748 "#endif\n"
749 "\n"
750 "#ifdef USEGAMMARAMPS\n"
751 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
752 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
753 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
754 "#endif\n"
755 "}\n"
756 "#endif\n"
757 "#else // !MODE_POSTPROCESS\n"
758 "\n"
759 "\n"
760 "\n"
761 "\n"
762 "#ifdef MODE_GENERIC\n"
763 "#ifdef USEDIFFUSE\n"
764 "varying vec2 TexCoord1;\n"
765 "#endif\n"
766 "#ifdef USESPECULAR\n"
767 "varying vec2 TexCoord2;\n"
768 "#endif\n"
769 "#ifdef VERTEX_SHADER\n"
770 "void main(void)\n"
771 "{\n"
772 "       gl_FrontColor = gl_Color;\n"
773 "#ifdef USEDIFFUSE\n"
774 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
775 "#endif\n"
776 "#ifdef USESPECULAR\n"
777 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
778 "#endif\n"
779 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
780 "}\n"
781 "#endif\n"
782 "\n"
783 "#ifdef FRAGMENT_SHADER\n"
784 "#ifdef USEDIFFUSE\n"
785 "uniform sampler2D Texture_First;\n"
786 "#endif\n"
787 "#ifdef USESPECULAR\n"
788 "uniform sampler2D Texture_Second;\n"
789 "#endif\n"
790 "\n"
791 "void main(void)\n"
792 "{\n"
793 "       gl_FragColor = gl_Color;\n"
794 "#ifdef USEDIFFUSE\n"
795 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
796 "#endif\n"
797 "\n"
798 "#ifdef USESPECULAR\n"
799 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
800 "# ifdef USECOLORMAPPING\n"
801 "       gl_FragColor *= tex2;\n"
802 "# endif\n"
803 "# ifdef USEGLOW\n"
804 "       gl_FragColor += tex2;\n"
805 "# endif\n"
806 "# ifdef USEVERTEXTEXTUREBLEND\n"
807 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
808 "# endif\n"
809 "#endif\n"
810 "}\n"
811 "#endif\n"
812 "#else // !MODE_GENERIC\n"
813 "\n"
814 "\n"
815 "\n"
816 "\n"
817 "#ifdef MODE_BLOOMBLUR\n"
818 "varying TexCoord;\n"
819 "#ifdef VERTEX_SHADER\n"
820 "void main(void)\n"
821 "{\n"
822 "       gl_FrontColor = gl_Color;\n"
823 "       TexCoord = gl_MultiTexCoord0.xy;\n"
824 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
825 "}\n"
826 "#endif\n"
827 "\n"
828 "#ifdef FRAGMENT_SHADER\n"
829 "uniform sampler2D Texture_First;\n"
830 "uniform vec4 BloomBlur_Parameters;\n"
831 "\n"
832 "void main(void)\n"
833 "{\n"
834 "       int i;\n"
835 "       vec2 tc = TexCoord;\n"
836 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
837 "       tc += BloomBlur_Parameters.xy;\n"
838 "       for (i = 1;i < SAMPLES;i++)\n"
839 "       {\n"
840 "               color += texture2D(Texture_First, tc).rgb;\n"
841 "               tc += BloomBlur_Parameters.xy;\n"
842 "       }\n"
843 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
844 "}\n"
845 "#endif\n"
846 "#else // !MODE_BLOOMBLUR\n"
847 "#ifdef MODE_REFRACTION\n"
848 "varying vec2 TexCoord;\n"
849 "varying vec4 ModelViewProjectionPosition;\n"
850 "uniform mat4 TexMatrix;\n"
851 "#ifdef VERTEX_SHADER\n"
852 "\n"
853 "void main(void)\n"
854 "{\n"
855 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
856 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
857 "       ModelViewProjectionPosition = gl_Position;\n"
858 "}\n"
859 "#endif\n"
860 "\n"
861 "#ifdef FRAGMENT_SHADER\n"
862 "uniform sampler2D Texture_Normal;\n"
863 "uniform sampler2D Texture_Refraction;\n"
864 "uniform sampler2D Texture_Reflection;\n"
865 "\n"
866 "uniform vec4 DistortScaleRefractReflect;\n"
867 "uniform vec4 ScreenScaleRefractReflect;\n"
868 "uniform vec4 ScreenCenterRefractReflect;\n"
869 "uniform vec4 RefractColor;\n"
870 "uniform vec4 ReflectColor;\n"
871 "uniform float ReflectFactor;\n"
872 "uniform float ReflectOffset;\n"
873 "\n"
874 "void main(void)\n"
875 "{\n"
876 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
877 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
878 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
879 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
880 "       // FIXME temporary hack to detect the case that the reflection\n"
881 "       // gets blackened at edges due to leaving the area that contains actual\n"
882 "       // content.\n"
883 "       // Remove this 'ack once we have a better way to stop this thing from\n"
884 "       // 'appening.\n"
885 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
886 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
887 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
888 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
889 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
890 "       gl_FragColor = texture2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
891 "}\n"
892 "#endif\n"
893 "#else // !MODE_REFRACTION\n"
894 "\n"
895 "\n"
896 "\n"
897 "\n"
898 "#ifdef MODE_WATER\n"
899 "varying vec2 TexCoord;\n"
900 "varying vec3 EyeVector;\n"
901 "varying vec4 ModelViewProjectionPosition;\n"
902 "#ifdef VERTEX_SHADER\n"
903 "uniform vec3 EyePosition;\n"
904 "uniform mat4 TexMatrix;\n"
905 "\n"
906 "void main(void)\n"
907 "{\n"
908 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
909 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
910 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
911 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
912 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
913 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
914 "       ModelViewProjectionPosition = gl_Position;\n"
915 "}\n"
916 "#endif\n"
917 "\n"
918 "#ifdef FRAGMENT_SHADER\n"
919 "uniform sampler2D Texture_Normal;\n"
920 "uniform sampler2D Texture_Refraction;\n"
921 "uniform sampler2D Texture_Reflection;\n"
922 "\n"
923 "uniform vec4 DistortScaleRefractReflect;\n"
924 "uniform vec4 ScreenScaleRefractReflect;\n"
925 "uniform vec4 ScreenCenterRefractReflect;\n"
926 "uniform vec4 RefractColor;\n"
927 "uniform vec4 ReflectColor;\n"
928 "uniform float ReflectFactor;\n"
929 "uniform float ReflectOffset;\n"
930 "\n"
931 "void main(void)\n"
932 "{\n"
933 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
934 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
935 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
936 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
937 "       vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
938 "       // FIXME temporary hack to detect the case that the reflection\n"
939 "       // gets blackened at edges due to leaving the area that contains actual\n"
940 "       // content.\n"
941 "       // Remove this 'ack once we have a better way to stop this thing from\n"
942 "       // 'appening.\n"
943 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, 0.01)).rgb) / 0.05);\n"
944 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.01, -0.01)).rgb) / 0.05);\n"
945 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
946 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
947 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
948 "       f       = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, 0.01)).rgb) / 0.05);\n"
949 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.01, -0.01)).rgb) / 0.05);\n"
950 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
951 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
952 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
953 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
954 "       gl_FragColor = mix(texture2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, texture2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
955 "}\n"
956 "#endif\n"
957 "#else // !MODE_WATER\n"
958 "\n"
959 "\n"
960 "\n"
961 "\n"
962 "// common definitions between vertex shader and fragment shader:\n"
963 "\n"
964 "varying vec2 TexCoord;\n"
965 "#ifdef USEVERTEXTEXTUREBLEND\n"
966 "varying vec2 TexCoord2;\n"
967 "#endif\n"
968 "#ifdef USELIGHTMAP\n"
969 "varying vec2 TexCoordLightmap;\n"
970 "#endif\n"
971 "\n"
972 "#ifdef MODE_LIGHTSOURCE\n"
973 "varying vec3 CubeVector;\n"
974 "#endif\n"
975 "\n"
976 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
977 "varying vec3 LightVector;\n"
978 "#endif\n"
979 "\n"
980 "#ifdef USEEYEVECTOR\n"
981 "varying vec3 EyeVector;\n"
982 "#endif\n"
983 "#ifdef USEFOG\n"
984 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
985 "#endif\n"
986 "\n"
987 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
988 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
989 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
990 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
991 "#endif\n"
992 "\n"
993 "#ifdef USEREFLECTION\n"
994 "varying vec4 ModelViewProjectionPosition;\n"
995 "#endif\n"
996 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
997 "uniform vec3 LightPosition;\n"
998 "varying vec4 ModelViewPosition;\n"
999 "#endif\n"
1000 "\n"
1001 "#ifdef MODE_LIGHTSOURCE\n"
1002 "uniform vec3 LightPosition;\n"
1003 "#endif\n"
1004 "uniform vec3 EyePosition;\n"
1005 "#ifdef MODE_LIGHTDIRECTION\n"
1006 "uniform vec3 LightDir;\n"
1007 "#endif\n"
1008 "uniform vec4 FogPlane;\n"
1009 "\n"
1010 "#ifdef USESHADOWMAPORTHO\n"
1011 "varying vec3 ShadowMapTC;\n"
1012 "#endif\n"
1013 "\n"
1014 "\n"
1015 "\n"
1016 "\n"
1017 "\n"
1018 "// 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"
1019 "\n"
1020 "// fragment shader specific:\n"
1021 "#ifdef FRAGMENT_SHADER\n"
1022 "\n"
1023 "uniform sampler2D Texture_Normal;\n"
1024 "uniform sampler2D Texture_Color;\n"
1025 "uniform sampler2D Texture_Gloss;\n"
1026 "#ifdef USEGLOW\n"
1027 "uniform sampler2D Texture_Glow;\n"
1028 "#endif\n"
1029 "#ifdef USEVERTEXTEXTUREBLEND\n"
1030 "uniform sampler2D Texture_SecondaryNormal;\n"
1031 "uniform sampler2D Texture_SecondaryColor;\n"
1032 "uniform sampler2D Texture_SecondaryGloss;\n"
1033 "#ifdef USEGLOW\n"
1034 "uniform sampler2D Texture_SecondaryGlow;\n"
1035 "#endif\n"
1036 "#endif\n"
1037 "#ifdef USECOLORMAPPING\n"
1038 "uniform sampler2D Texture_Pants;\n"
1039 "uniform sampler2D Texture_Shirt;\n"
1040 "#endif\n"
1041 "#ifdef USEFOG\n"
1042 "#ifdef USEFOGHEIGHTTEXTURE\n"
1043 "uniform sampler2D Texture_FogHeightTexture;\n"
1044 "#endif\n"
1045 "uniform sampler2D Texture_FogMask;\n"
1046 "#endif\n"
1047 "#ifdef USELIGHTMAP\n"
1048 "uniform sampler2D Texture_Lightmap;\n"
1049 "#endif\n"
1050 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1051 "uniform sampler2D Texture_Deluxemap;\n"
1052 "#endif\n"
1053 "#ifdef USEREFLECTION\n"
1054 "uniform sampler2D Texture_Reflection;\n"
1055 "#endif\n"
1056 "\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform sampler2D Texture_ScreenDepth;\n"
1059 "uniform sampler2D Texture_ScreenNormalMap;\n"
1060 "#endif\n"
1061 "#ifdef USEDEFERREDLIGHTMAP\n"
1062 "uniform sampler2D Texture_ScreenDiffuse;\n"
1063 "uniform sampler2D Texture_ScreenSpecular;\n"
1064 "#endif\n"
1065 "\n"
1066 "uniform myhalf3 Color_Pants;\n"
1067 "uniform myhalf3 Color_Shirt;\n"
1068 "uniform myhalf3 FogColor;\n"
1069 "\n"
1070 "#ifdef USEFOG\n"
1071 "uniform float FogRangeRecip;\n"
1072 "uniform float FogPlaneViewDist;\n"
1073 "uniform float FogHeightFade;\n"
1074 "vec3 FogVertex(vec3 surfacecolor)\n"
1075 "{\n"
1076 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1077 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1078 "       float fogfrac;\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1081 "       fogfrac = fogheightpixel.a;\n"
1082 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1083 "#else\n"
1084 "# ifdef USEFOGOUTSIDE\n"
1085 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1086 "# else\n"
1087 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1088 "# endif\n"
1089 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1090 "#endif\n"
1091 "}\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef USEOFFSETMAPPING\n"
1095 "uniform float OffsetMapping_Scale;\n"
1096 "vec2 OffsetMapping(vec2 TexCoord)\n"
1097 "{\n"
1098 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1099 "       // 14 sample relief mapping: linear search and then binary search\n"
1100 "       // this basically steps forward a small amount repeatedly until it finds\n"
1101 "       // itself inside solid, then jitters forward and back using decreasing\n"
1102 "       // amounts to find the impact\n"
1103 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1104 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1105 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1106 "       vec3 RT = vec3(TexCoord, 1);\n"
1107 "       OffsetVector *= 0.1;\n"
1108 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1109 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1110 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1111 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1112 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1113 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1114 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1115 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\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)          - 0.5);\n"
1118 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1119 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1120 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1121 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1122 "       return RT.xy;\n"
1123 "#else\n"
1124 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1125 "       // this basically moves forward the full distance, and then backs up based\n"
1126 "       // on height of samples\n"
1127 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1128 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1129 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1130 "       TexCoord += OffsetVector;\n"
1131 "       OffsetVector *= 0.333;\n"
1132 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1133 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1134 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1135 "       return TexCoord;\n"
1136 "#endif\n"
1137 "}\n"
1138 "#endif // USEOFFSETMAPPING\n"
1139 "\n"
1140 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1141 "uniform sampler2D Texture_Attenuation;\n"
1142 "uniform samplerCube Texture_Cube;\n"
1143 "#endif\n"
1144 "\n"
1145 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1146 "\n"
1147 "#ifdef USESHADOWMAP2D\n"
1148 "# ifdef USESHADOWSAMPLER\n"
1149 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1150 "# else\n"
1151 "uniform sampler2D Texture_ShadowMap2D;\n"
1152 "# endif\n"
1153 "#endif\n"
1154 "\n"
1155 "#ifdef USESHADOWMAPVSDCT\n"
1156 "uniform samplerCube Texture_CubeProjection;\n"
1157 "#endif\n"
1158 "\n"
1159 "#if defined(USESHADOWMAP2D)\n"
1160 "uniform vec2 ShadowMap_TextureScale;\n"
1161 "uniform vec4 ShadowMap_Parameters;\n"
1162 "#endif\n"
1163 "\n"
1164 "#if defined(USESHADOWMAP2D)\n"
1165 "# ifdef USESHADOWMAPORTHO\n"
1166 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1167 "# else\n"
1168 "#  ifdef USESHADOWMAPVSDCT\n"
1169 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1170 "{\n"
1171 "       vec3 adir = abs(dir);\n"
1172 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1173 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1174 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1175 "}\n"
1176 "#  else\n"
1177 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1178 "{\n"
1179 "       vec3 adir = abs(dir);\n"
1180 "       float ma = adir.z;\n"
1181 "       vec4 proj = vec4(dir, 2.5);\n"
1182 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1183 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1184 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1185 "       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"
1186 "}\n"
1187 "#  endif\n"
1188 "# endif\n"
1189 "#endif // defined(USESHADOWMAP2D)\n"
1190 "\n"
1191 "# ifdef USESHADOWMAP2D\n"
1192 "float ShadowMapCompare(vec3 dir)\n"
1193 "{\n"
1194 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1195 "       float f;\n"
1196 "\n"
1197 "#  ifdef USESHADOWSAMPLER\n"
1198 "#    ifdef USESHADOWMAPPCF\n"
1199 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1200 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1201 "       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"
1202 "#    else\n"
1203 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1204 "#    endif\n"
1205 "#  else\n"
1206 "#    ifdef USESHADOWMAPPCF\n"
1207 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1208 "#      ifdef GL_ARB_texture_gather\n"
1209 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1210 "#      else\n"
1211 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1212 "#      endif\n"
1213 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1214 "#      if USESHADOWMAPPCF > 1\n"
1215 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1216 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1217 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1218 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1219 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1220 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1221 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1222 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1223 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1224 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1225 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1226 "       locols.yz += group2.ab;\n"
1227 "       hicols.yz += group8.rg;\n"
1228 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1229 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1230 "                               mix(locols, hicols, offset.y);\n"
1231 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1232 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1233 "       f = dot(cols, vec4(1.0/25.0));\n"
1234 "#      else\n"
1235 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1236 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1237 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1238 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1239 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1240 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1241 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1242 "#      endif\n"
1243 "#     else\n"
1244 "#      ifdef GL_EXT_gpu_shader4\n"
1245 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1248 "#      endif\n"
1249 "#      if USESHADOWMAPPCF > 1\n"
1250 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1251 "       center *= ShadowMap_TextureScale;\n"
1252 "       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"
1253 "       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"
1254 "       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"
1255 "       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"
1256 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1257 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1258 "#      else\n"
1259 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1260 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1261 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1262 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1263 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1264 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1265 "#      endif\n"
1266 "#     endif\n"
1267 "#    else\n"
1268 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1269 "#    endif\n"
1270 "#  endif\n"
1271 "#  ifdef USESHADOWMAPORTHO\n"
1272 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1273 "#  else\n"
1274 "       return f;\n"
1275 "#  endif\n"
1276 "}\n"
1277 "# endif\n"
1278 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1279 "#endif // FRAGMENT_SHADER\n"
1280 "\n"
1281 "\n"
1282 "\n"
1283 "\n"
1284 "#ifdef MODE_DEFERREDGEOMETRY\n"
1285 "#ifdef VERTEX_SHADER\n"
1286 "uniform mat4 TexMatrix;\n"
1287 "#ifdef USEVERTEXTEXTUREBLEND\n"
1288 "uniform mat4 BackgroundTexMatrix;\n"
1289 "#endif\n"
1290 "uniform mat4 ModelViewMatrix;\n"
1291 "void main(void)\n"
1292 "{\n"
1293 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1294 "#ifdef USEVERTEXTEXTUREBLEND\n"
1295 "       gl_FrontColor = gl_Color;\n"
1296 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1297 "#endif\n"
1298 "\n"
1299 "       // transform unnormalized eye direction into tangent space\n"
1300 "#ifdef USEOFFSETMAPPING\n"
1301 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1302 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1303 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1304 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1305 "#endif\n"
1306 "\n"
1307 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1308 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1309 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1310 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1311 "}\n"
1312 "#endif // VERTEX_SHADER\n"
1313 "\n"
1314 "#ifdef FRAGMENT_SHADER\n"
1315 "void main(void)\n"
1316 "{\n"
1317 "#ifdef USEOFFSETMAPPING\n"
1318 "       // apply offsetmapping\n"
1319 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1320 "#define TexCoord TexCoordOffset\n"
1321 "#endif\n"
1322 "\n"
1323 "#ifdef USEALPHAKILL\n"
1324 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1325 "               discard;\n"
1326 "#endif\n"
1327 "\n"
1328 "#ifdef USEVERTEXTEXTUREBLEND\n"
1329 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1330 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1331 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1332 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1333 "#endif\n"
1334 "\n"
1335 "#ifdef USEVERTEXTEXTUREBLEND\n"
1336 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1337 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1338 "#else\n"
1339 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1340 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1341 "#endif\n"
1342 "\n"
1343 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1344 "}\n"
1345 "#endif // FRAGMENT_SHADER\n"
1346 "#else // !MODE_DEFERREDGEOMETRY\n"
1347 "\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1352 "#ifdef VERTEX_SHADER\n"
1353 "uniform mat4 ModelViewMatrix;\n"
1354 "void main(void)\n"
1355 "{\n"
1356 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1357 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1358 "}\n"
1359 "#endif // VERTEX_SHADER\n"
1360 "\n"
1361 "#ifdef FRAGMENT_SHADER\n"
1362 "uniform mat4 ViewToLight;\n"
1363 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1364 "uniform vec2 ScreenToDepth;\n"
1365 "uniform myhalf3 DeferredColor_Ambient;\n"
1366 "uniform myhalf3 DeferredColor_Diffuse;\n"
1367 "#ifdef USESPECULAR\n"
1368 "uniform myhalf3 DeferredColor_Specular;\n"
1369 "uniform myhalf SpecularPower;\n"
1370 "#endif\n"
1371 "uniform myhalf2 PixelToScreenTexCoord;\n"
1372 "void main(void)\n"
1373 "{\n"
1374 "       // calculate viewspace pixel position\n"
1375 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1376 "       vec3 position;\n"
1377 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1378 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1379 "       // decode viewspace pixel normal\n"
1380 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1381 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1382 "       // surfacenormal = pixel normal in viewspace\n"
1383 "       // LightVector = pixel to light in viewspace\n"
1384 "       // CubeVector = position in lightspace\n"
1385 "       // eyevector = pixel to view in viewspace\n"
1386 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1387 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1388 "#ifdef USEDIFFUSE\n"
1389 "       // calculate diffuse shading\n"
1390 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1391 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1392 "#endif\n"
1393 "#ifdef USESPECULAR\n"
1394 "       // calculate directional shading\n"
1395 "       vec3 eyevector = position * -1.0;\n"
1396 "#  ifdef USEEXACTSPECULARMATH\n"
1397 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1398 "#  else\n"
1399 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1400 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1401 "#  endif\n"
1402 "#endif\n"
1403 "\n"
1404 "#if defined(USESHADOWMAP2D)\n"
1405 "       fade *= ShadowMapCompare(CubeVector);\n"
1406 "#endif\n"
1407 "\n"
1408 "#ifdef USEDIFFUSE\n"
1409 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1410 "#else\n"
1411 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1412 "#endif\n"
1413 "#ifdef USESPECULAR\n"
1414 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1415 "#else\n"
1416 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1417 "#endif\n"
1418 "\n"
1419 "# ifdef USECUBEFILTER\n"
1420 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1421 "       gl_FragData[0].rgb *= cubecolor;\n"
1422 "       gl_FragData[1].rgb *= cubecolor;\n"
1423 "# endif\n"
1424 "}\n"
1425 "#endif // FRAGMENT_SHADER\n"
1426 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1427 "\n"
1428 "\n"
1429 "\n"
1430 "\n"
1431 "#ifdef VERTEX_SHADER\n"
1432 "uniform mat4 TexMatrix;\n"
1433 "#ifdef USEVERTEXTEXTUREBLEND\n"
1434 "uniform mat4 BackgroundTexMatrix;\n"
1435 "#endif\n"
1436 "#ifdef MODE_LIGHTSOURCE\n"
1437 "uniform mat4 ModelToLight;\n"
1438 "#endif\n"
1439 "#ifdef USESHADOWMAPORTHO\n"
1440 "uniform mat4 ShadowMapMatrix;\n"
1441 "#endif\n"
1442 "void main(void)\n"
1443 "{\n"
1444 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1445 "       gl_FrontColor = gl_Color;\n"
1446 "#endif\n"
1447 "       // copy the surface texcoord\n"
1448 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1449 "#ifdef USEVERTEXTEXTUREBLEND\n"
1450 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1451 "#endif\n"
1452 "#ifdef USELIGHTMAP\n"
1453 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1454 "#endif\n"
1455 "\n"
1456 "#ifdef MODE_LIGHTSOURCE\n"
1457 "       // transform vertex position into light attenuation/cubemap space\n"
1458 "       // (-1 to +1 across the light box)\n"
1459 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1460 "\n"
1461 "# ifdef USEDIFFUSE\n"
1462 "       // transform unnormalized light direction into tangent space\n"
1463 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1464 "       //  normalize it per pixel)\n"
1465 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1466 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1467 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1468 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1469 "# endif\n"
1470 "#endif\n"
1471 "\n"
1472 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1473 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1474 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1475 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1476 "#endif\n"
1477 "\n"
1478 "       // transform unnormalized eye direction into tangent space\n"
1479 "#ifdef USEEYEVECTOR\n"
1480 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1481 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1482 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1483 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1484 "#endif\n"
1485 "\n"
1486 "#ifdef USEFOG\n"
1487 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1488 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1489 "#endif\n"
1490 "\n"
1491 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1492 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1493 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1494 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1495 "#endif\n"
1496 "\n"
1497 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1498 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1499 "\n"
1500 "#ifdef USESHADOWMAPORTHO\n"
1501 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1502 "#endif\n"
1503 "\n"
1504 "#ifdef USEREFLECTION\n"
1505 "       ModelViewProjectionPosition = gl_Position;\n"
1506 "#endif\n"
1507 "}\n"
1508 "#endif // VERTEX_SHADER\n"
1509 "\n"
1510 "\n"
1511 "\n"
1512 "\n"
1513 "#ifdef FRAGMENT_SHADER\n"
1514 "#ifdef USEDEFERREDLIGHTMAP\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "uniform myhalf3 DeferredMod_Diffuse;\n"
1517 "uniform myhalf3 DeferredMod_Specular;\n"
1518 "#endif\n"
1519 "uniform myhalf3 Color_Ambient;\n"
1520 "uniform myhalf3 Color_Diffuse;\n"
1521 "uniform myhalf3 Color_Specular;\n"
1522 "uniform myhalf SpecularPower;\n"
1523 "#ifdef USEGLOW\n"
1524 "uniform myhalf3 Color_Glow;\n"
1525 "#endif\n"
1526 "uniform myhalf Alpha;\n"
1527 "#ifdef USEREFLECTION\n"
1528 "uniform vec4 DistortScaleRefractReflect;\n"
1529 "uniform vec4 ScreenScaleRefractReflect;\n"
1530 "uniform vec4 ScreenCenterRefractReflect;\n"
1531 "uniform myhalf4 ReflectColor;\n"
1532 "#endif\n"
1533 "#ifdef USEREFLECTCUBE\n"
1534 "uniform mat4 ModelToReflectCube;\n"
1535 "uniform sampler2D Texture_ReflectMask;\n"
1536 "uniform samplerCube Texture_ReflectCube;\n"
1537 "#endif\n"
1538 "#ifdef MODE_LIGHTDIRECTION\n"
1539 "uniform myhalf3 LightColor;\n"
1540 "#endif\n"
1541 "#ifdef MODE_LIGHTSOURCE\n"
1542 "uniform myhalf3 LightColor;\n"
1543 "#endif\n"
1544 "void main(void)\n"
1545 "{\n"
1546 "#ifdef USEOFFSETMAPPING\n"
1547 "       // apply offsetmapping\n"
1548 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1549 "#define TexCoord TexCoordOffset\n"
1550 "#endif\n"
1551 "\n"
1552 "       // combine the diffuse textures (base, pants, shirt)\n"
1553 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1554 "#ifdef USEALPHAKILL\n"
1555 "       if (color.a < 0.5)\n"
1556 "               discard;\n"
1557 "#endif\n"
1558 "       color.a *= Alpha;\n"
1559 "#ifdef USECOLORMAPPING\n"
1560 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1561 "#endif\n"
1562 "#ifdef USEVERTEXTEXTUREBLEND\n"
1563 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1564 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1565 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1566 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1567 "       color.a = 1.0;\n"
1568 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1569 "#endif\n"
1570 "\n"
1571 "       // get the surface normal\n"
1572 "#ifdef USEVERTEXTEXTUREBLEND\n"
1573 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1574 "#else\n"
1575 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1576 "#endif\n"
1577 "\n"
1578 "       // get the material colors\n"
1579 "       myhalf3 diffusetex = color.rgb;\n"
1580 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1581 "# ifdef USEVERTEXTEXTUREBLEND\n"
1582 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1583 "# else\n"
1584 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1585 "# endif\n"
1586 "#endif\n"
1587 "\n"
1588 "#ifdef USEREFLECTCUBE\n"
1589 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1590 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1591 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1592 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1593 "#endif\n"
1594 "\n"
1595 "\n"
1596 "\n"
1597 "\n"
1598 "#ifdef MODE_LIGHTSOURCE\n"
1599 "       // light source\n"
1600 "#ifdef USEDIFFUSE\n"
1601 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1602 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1603 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1604 "#ifdef USESPECULAR\n"
1605 "#ifdef USEEXACTSPECULARMATH\n"
1606 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1607 "#else\n"
1608 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1609 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1610 "#endif\n"
1611 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1612 "#endif\n"
1613 "#else\n"
1614 "       color.rgb = diffusetex * Color_Ambient;\n"
1615 "#endif\n"
1616 "       color.rgb *= LightColor;\n"
1617 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1618 "#if defined(USESHADOWMAP2D)\n"
1619 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1620 "#endif\n"
1621 "# ifdef USECUBEFILTER\n"
1622 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1623 "# endif\n"
1624 "#endif // MODE_LIGHTSOURCE\n"
1625 "\n"
1626 "\n"
1627 "\n"
1628 "\n"
1629 "#ifdef MODE_LIGHTDIRECTION\n"
1630 "#define SHADING\n"
1631 "#ifdef USEDIFFUSE\n"
1632 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1633 "#endif\n"
1634 "#define lightcolor LightColor\n"
1635 "#endif // MODE_LIGHTDIRECTION\n"
1636 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1637 "#define SHADING\n"
1638 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1639 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1640 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1641 "       // convert modelspace light vector to tangentspace\n"
1642 "       myhalf3 lightnormal;\n"
1643 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1644 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1645 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1646 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1647 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1648 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1649 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1650 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1651 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1652 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1653 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1654 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1655 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1656 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1657 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1658 "#define SHADING\n"
1659 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1660 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1661 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1662 "#endif\n"
1663 "\n"
1664 "\n"
1665 "\n"
1666 "\n"
1667 "#ifdef MODE_LIGHTMAP\n"
1668 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1669 "#endif // MODE_LIGHTMAP\n"
1670 "#ifdef MODE_VERTEXCOLOR\n"
1671 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1672 "#endif // MODE_VERTEXCOLOR\n"
1673 "#ifdef MODE_FLATCOLOR\n"
1674 "       color.rgb = diffusetex * Color_Ambient;\n"
1675 "#endif // MODE_FLATCOLOR\n"
1676 "\n"
1677 "\n"
1678 "\n"
1679 "\n"
1680 "#ifdef SHADING\n"
1681 "# ifdef USEDIFFUSE\n"
1682 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1683 "#  ifdef USESPECULAR\n"
1684 "#   ifdef USEEXACTSPECULARMATH\n"
1685 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1686 "#   else\n"
1687 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1688 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1689 "#   endif\n"
1690 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1691 "#  else\n"
1692 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1693 "#  endif\n"
1694 "# else\n"
1695 "       color.rgb = diffusetex * Color_Ambient;\n"
1696 "# endif\n"
1697 "#endif\n"
1698 "\n"
1699 "#ifdef USESHADOWMAPORTHO\n"
1700 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1701 "#endif\n"
1702 "\n"
1703 "#ifdef USEDEFERREDLIGHTMAP\n"
1704 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1705 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1706 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1707 "#endif\n"
1708 "\n"
1709 "#ifdef USEGLOW\n"
1710 "#ifdef USEVERTEXTEXTUREBLEND\n"
1711 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1712 "#else\n"
1713 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1714 "#endif\n"
1715 "#endif\n"
1716 "\n"
1717 "#ifdef USEFOG\n"
1718 "       color.rgb = FogVertex(color.rgb);\n"
1719 "#endif\n"
1720 "\n"
1721 "       // 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"
1722 "#ifdef USEREFLECTION\n"
1723 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1724 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1725 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1726 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1727 "       // FIXME temporary hack to detect the case that the reflection\n"
1728 "       // gets blackened at edges due to leaving the area that contains actual\n"
1729 "       // content.\n"
1730 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1731 "       // 'appening.\n"
1732 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1733 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1734 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1735 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1736 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1737 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1738 "#endif\n"
1739 "\n"
1740 "       gl_FragColor = vec4(color);\n"
1741 "}\n"
1742 "#endif // FRAGMENT_SHADER\n"
1743 "\n"
1744 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1745 "#endif // !MODE_DEFERREDGEOMETRY\n"
1746 "#endif // !MODE_WATER\n"
1747 "#endif // !MODE_REFRACTION\n"
1748 "#endif // !MODE_BLOOMBLUR\n"
1749 "#endif // !MODE_GENERIC\n"
1750 "#endif // !MODE_POSTPROCESS\n"
1751 "#endif // !MODE_SHOWDEPTH\n"
1752 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1753 ;
1754
1755 /*
1756 =========================================================================================================================================================
1757
1758
1759
1760 =========================================================================================================================================================
1761
1762
1763
1764 =========================================================================================================================================================
1765
1766
1767
1768 =========================================================================================================================================================
1769
1770
1771
1772 =========================================================================================================================================================
1773
1774
1775
1776 =========================================================================================================================================================
1777
1778
1779
1780 =========================================================================================================================================================
1781 */
1782
1783 const char *builtincgshaderstring =
1784 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1785 "// written by Forest 'LordHavoc' Hale\n"
1786 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1787 "\n"
1788 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1789 "#if defined(USEREFLECTION)\n"
1790 "#undef USESHADOWMAPORTHO\n"
1791 "#endif\n"
1792 "\n"
1793 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1794 "# define USEFOG\n"
1795 "#endif\n"
1796 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1797 "#define USELIGHTMAP\n"
1798 "#endif\n"
1799 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE)\n"
1800 "#define USEEYEVECTOR\n"
1801 "#endif\n"
1802 "\n"
1803 "#ifdef FRAGMENT_SHADER\n"
1804 "#ifdef HLSL\n"
1805 "//#undef USESHADOWMAPPCF\n"
1806 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1807 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1808 "#else\n"
1809 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1810 "#endif\n"
1811 "#endif\n"
1812 "\n"
1813 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1814 "#ifdef VERTEX_SHADER\n"
1815 "void main\n"
1816 "(\n"
1817 "float4 gl_Vertex : POSITION,\n"
1818 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1819 "out float4 gl_Position : POSITION,\n"
1820 "out float Depth : TEXCOORD0\n"
1821 ")\n"
1822 "{\n"
1823 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1824 "       Depth = gl_Position.z;\n"
1825 "}\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef FRAGMENT_SHADER\n"
1829 "void main\n"
1830 "(\n"
1831 "float Depth : TEXCOORD0,\n"
1832 "out float4 gl_FragColor : COLOR\n"
1833 ")\n"
1834 "{\n"
1835 "//     float3 temp = float3(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0));\n"
1836 "       float3 temp = float3(Depth,Depth*256.0,Depth*65536.0);\n"
1837 "       temp.yz -= floor(temp.yz);\n"
1838 "       gl_FragColor = float4(temp,0);\n"
1839 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1840 "}\n"
1841 "#endif\n"
1842 "#else // !MODE_DEPTH_ORSHADOW\n"
1843 "\n"
1844 "\n"
1845 "\n"
1846 "\n"
1847 "#ifdef MODE_SHOWDEPTH\n"
1848 "#ifdef VERTEX_SHADER\n"
1849 "void main\n"
1850 "(\n"
1851 "float4 gl_Vertex : POSITION,\n"
1852 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1853 "out float4 gl_Position : POSITION,\n"
1854 "out float4 gl_FrontColor : COLOR0\n"
1855 ")\n"
1856 "{\n"
1857 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1858 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1859 "}\n"
1860 "#endif\n"
1861 "\n"
1862 "#ifdef FRAGMENT_SHADER\n"
1863 "void main\n"
1864 "(\n"
1865 "float4 gl_FrontColor : COLOR0,\n"
1866 "out float4 gl_FragColor : COLOR\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_FragColor = gl_FrontColor;\n"
1870 "}\n"
1871 "#endif\n"
1872 "#else // !MODE_SHOWDEPTH\n"
1873 "\n"
1874 "\n"
1875 "\n"
1876 "\n"
1877 "#ifdef MODE_POSTPROCESS\n"
1878 "\n"
1879 "#ifdef VERTEX_SHADER\n"
1880 "void main\n"
1881 "(\n"
1882 "float4 gl_Vertex : POSITION,\n"
1883 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1884 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1885 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1886 "out float4 gl_Position : POSITION,\n"
1887 "out float2 TexCoord1 : TEXCOORD0,\n"
1888 "out float2 TexCoord2 : TEXCOORD1\n"
1889 ")\n"
1890 "{\n"
1891 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1892 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1893 "#ifdef USEBLOOM\n"
1894 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1895 "#endif\n"
1896 "}\n"
1897 "#endif\n"
1898 "\n"
1899 "#ifdef FRAGMENT_SHADER\n"
1900 "void main\n"
1901 "(\n"
1902 "float2 TexCoord1 : TEXCOORD0,\n"
1903 "float2 TexCoord2 : TEXCOORD1,\n"
1904 "uniform sampler Texture_First : register(s0),\n"
1905 "#ifdef USEBLOOM\n"
1906 "uniform sampler Texture_Second : register(s1),\n"
1907 "#endif\n"
1908 "#ifdef USEGAMMARAMPS\n"
1909 "uniform sampler Texture_GammaRamps : register(s2),\n"
1910 "#endif\n"
1911 "#ifdef USESATURATION\n"
1912 "uniform float Saturation : register(c30),\n"
1913 "#endif\n"
1914 "#ifdef USEVIEWTINT\n"
1915 "uniform float4 ViewTintColor : register(c41),\n"
1916 "#endif\n"
1917 "uniform float4 UserVec1 : register(c37),\n"
1918 "uniform float4 UserVec2 : register(c38),\n"
1919 "uniform float4 UserVec3 : register(c39),\n"
1920 "uniform float4 UserVec4 : register(c40),\n"
1921 "uniform float ClientTime : register(c2),\n"
1922 "uniform float2 PixelSize : register(c25),\n"
1923 "uniform float4 BloomColorSubtract : register(c43),\n"
1924 "out float4 gl_FragColor : COLOR\n"
1925 ")\n"
1926 "{\n"
1927 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1928 "#ifdef USEBLOOM\n"
1929 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1930 "#endif\n"
1931 "#ifdef USEVIEWTINT\n"
1932 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1933 "#endif\n"
1934 "\n"
1935 "#ifdef USEPOSTPROCESSING\n"
1936 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1937 "// 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"
1938 "       float sobel = 1.0;\n"
1939 "       // float2 ts = textureSize(Texture_First, 0);\n"
1940 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1941 "       float2 px = PixelSize;\n"
1942 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1943 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1944 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1945 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1946 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1947 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1948 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1949 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1950 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1951 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1952 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1953 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1954 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
1955 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
1956 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
1957 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
1958 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
1959 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
1960 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
1961 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
1962 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
1963 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
1964 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
1965 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
1966 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
1967 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
1968 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
1969 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
1970 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
1971 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
1972 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
1973 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
1974 "#endif\n"
1975 "\n"
1976 "#ifdef USESATURATION\n"
1977 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
1978 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
1979 "       //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
1980 "       gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
1981 "#endif\n"
1982 "\n"
1983 "#ifdef USEGAMMARAMPS\n"
1984 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
1985 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
1986 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
1987 "#endif\n"
1988 "}\n"
1989 "#endif\n"
1990 "#else // !MODE_POSTPROCESS\n"
1991 "\n"
1992 "\n"
1993 "\n"
1994 "\n"
1995 "#ifdef MODE_GENERIC\n"
1996 "#ifdef VERTEX_SHADER\n"
1997 "void main\n"
1998 "(\n"
1999 "float4 gl_Vertex : POSITION,\n"
2000 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2001 "float4 gl_Color : COLOR0,\n"
2002 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2003 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2004 "out float4 gl_Position : POSITION,\n"
2005 "out float4 gl_FrontColor : COLOR,\n"
2006 "out float2 TexCoord1 : TEXCOORD0,\n"
2007 "out float2 TexCoord2 : TEXCOORD1\n"
2008 ")\n"
2009 "{\n"
2010 "#ifdef HLSL\n"
2011 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2012 "#else\n"
2013 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2014 "#endif\n"
2015 "#ifdef USEDIFFUSE\n"
2016 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2017 "#endif\n"
2018 "#ifdef USESPECULAR\n"
2019 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2020 "#endif\n"
2021 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2022 "}\n"
2023 "#endif\n"
2024 "\n"
2025 "#ifdef FRAGMENT_SHADER\n"
2026 "\n"
2027 "void main\n"
2028 "(\n"
2029 "float4 gl_FrontColor : COLOR0,\n"
2030 "float2 TexCoord1 : TEXCOORD0,\n"
2031 "float2 TexCoord2 : TEXCOORD1,\n"
2032 "#ifdef USEDIFFUSE\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2034 "#endif\n"
2035 "#ifdef USESPECULAR\n"
2036 "uniform sampler Texture_Second : register(s1),\n"
2037 "#endif\n"
2038 "out float4 gl_FragColor : COLOR\n"
2039 ")\n"
2040 "{\n"
2041 "       gl_FragColor = gl_FrontColor;\n"
2042 "#ifdef USEDIFFUSE\n"
2043 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2044 "#endif\n"
2045 "\n"
2046 "#ifdef USESPECULAR\n"
2047 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2048 "# ifdef USECOLORMAPPING\n"
2049 "       gl_FragColor *= tex2;\n"
2050 "# endif\n"
2051 "# ifdef USEGLOW\n"
2052 "       gl_FragColor += tex2;\n"
2053 "# endif\n"
2054 "# ifdef USEVERTEXTEXTUREBLEND\n"
2055 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2056 "# endif\n"
2057 "#endif\n"
2058 "}\n"
2059 "#endif\n"
2060 "#else // !MODE_GENERIC\n"
2061 "\n"
2062 "\n"
2063 "\n"
2064 "\n"
2065 "#ifdef MODE_BLOOMBLUR\n"
2066 "#ifdef VERTEX_SHADER\n"
2067 "void main\n"
2068 "(\n"
2069 "float4 gl_Vertex : POSITION,\n"
2070 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2071 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2072 "out float4 gl_Position : POSITION,\n"
2073 "out float2 TexCoord : TEXCOORD0\n"
2074 ")\n"
2075 "{\n"
2076 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2077 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2078 "}\n"
2079 "#endif\n"
2080 "\n"
2081 "#ifdef FRAGMENT_SHADER\n"
2082 "\n"
2083 "void main\n"
2084 "(\n"
2085 "float2 TexCoord : TEXCOORD0,\n"
2086 "uniform sampler Texture_First : register(s0),\n"
2087 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2088 "out float4 gl_FragColor : COLOR\n"
2089 ")\n"
2090 "{\n"
2091 "       int i;\n"
2092 "       float2 tc = TexCoord;\n"
2093 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2094 "       tc += BloomBlur_Parameters.xy;\n"
2095 "       for (i = 1;i < SAMPLES;i++)\n"
2096 "       {\n"
2097 "               color += tex2D(Texture_First, tc).rgb;\n"
2098 "               tc += BloomBlur_Parameters.xy;\n"
2099 "       }\n"
2100 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2101 "}\n"
2102 "#endif\n"
2103 "#else // !MODE_BLOOMBLUR\n"
2104 "#ifdef MODE_REFRACTION\n"
2105 "#ifdef VERTEX_SHADER\n"
2106 "void main\n"
2107 "(\n"
2108 "float4 gl_Vertex : POSITION,\n"
2109 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2110 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2111 "uniform float4x4 TexMatrix : register(c0),\n"
2112 "uniform float3 EyePosition : register(c24),\n"
2113 "out float4 gl_Position : POSITION,\n"
2114 "out float2 TexCoord : TEXCOORD0,\n"
2115 "out float3 EyeVector : TEXCOORD1,\n"
2116 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2117 ")\n"
2118 "{\n"
2119 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2120 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 "       ModelViewProjectionPosition = gl_Position;\n"
2122 "}\n"
2123 "#endif\n"
2124 "\n"
2125 "#ifdef FRAGMENT_SHADER\n"
2126 "void main\n"
2127 "(\n"
2128 "float2 TexCoord : TEXCOORD0,\n"
2129 "float3 EyeVector : TEXCOORD1,\n"
2130 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2131 "uniform sampler Texture_Normal : register(s0),\n"
2132 "uniform sampler Texture_Refraction : register(s3),\n"
2133 "uniform sampler Texture_Reflection : register(s7),\n"
2134 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2135 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2136 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2137 "uniform float4 RefractColor : register(c29),\n"
2138 "out float4 gl_FragColor : COLOR\n"
2139 ")\n"
2140 "{\n"
2141 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2142 "       //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"
2143 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2144 "       float2 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.xy;\n"
2145 "       // FIXME temporary hack to detect the case that the reflection\n"
2146 "       // gets blackened at edges due to leaving the area that contains actual\n"
2147 "       // content.\n"
2148 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2149 "       // 'appening.\n"
2150 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2151 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2152 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2153 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2154 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2155 "       gl_FragColor = tex2D(Texture_Refraction, ScreenTexCoord) * RefractColor;\n"
2156 "}\n"
2157 "#endif\n"
2158 "#else // !MODE_REFRACTION\n"
2159 "\n"
2160 "\n"
2161 "\n"
2162 "\n"
2163 "#ifdef MODE_WATER\n"
2164 "#ifdef VERTEX_SHADER\n"
2165 "\n"
2166 "void main\n"
2167 "(\n"
2168 "float4 gl_Vertex : POSITION,\n"
2169 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2170 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2171 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2172 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2173 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2174 "uniform float4x4 TexMatrix : register(c0),\n"
2175 "uniform float3 EyePosition : register(c24),\n"
2176 "out float4 gl_Position : POSITION,\n"
2177 "out float2 TexCoord : TEXCOORD0,\n"
2178 "out float3 EyeVector : TEXCOORD1,\n"
2179 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2180 ")\n"
2181 "{\n"
2182 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2183 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2184 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2185 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2186 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2187 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2188 "       ModelViewProjectionPosition = gl_Position;\n"
2189 "}\n"
2190 "#endif\n"
2191 "\n"
2192 "#ifdef FRAGMENT_SHADER\n"
2193 "void main\n"
2194 "(\n"
2195 "float2 TexCoord : TEXCOORD0,\n"
2196 "float3 EyeVector : TEXCOORD1,\n"
2197 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2198 "uniform sampler Texture_Normal : register(s0),\n"
2199 "uniform sampler Texture_Refraction : register(s3),\n"
2200 "uniform sampler Texture_Reflection : register(s7),\n"
2201 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2202 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2203 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2204 "uniform float4 RefractColor : register(c29),\n"
2205 "uniform float4 ReflectColor : register(c26),\n"
2206 "uniform float ReflectFactor : register(c27),\n"
2207 "uniform float ReflectOffset : register(c28),\n"
2208 "out float4 gl_FragColor : COLOR\n"
2209 ")\n"
2210 "{\n"
2211 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2212 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2213 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2214 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2215 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2216 "       // FIXME temporary hack to detect the case that the reflection\n"
2217 "       // gets blackened at edges due to leaving the area that contains actual\n"
2218 "       // content.\n"
2219 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2220 "       // 'appening.\n"
2221 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2222 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2223 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2224 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2225 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2226 "       f       = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2227 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2228 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2229 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2230 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2231 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2232 "       gl_FragColor = lerp(tex2D(Texture_Refraction, ScreenTexCoord.xy) * RefractColor, tex2D(Texture_Reflection, ScreenTexCoord.zw) * ReflectColor, Fresnel);\n"
2233 "}\n"
2234 "#endif\n"
2235 "#else // !MODE_WATER\n"
2236 "\n"
2237 "\n"
2238 "\n"
2239 "\n"
2240 "// 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"
2241 "\n"
2242 "// fragment shader specific:\n"
2243 "#ifdef FRAGMENT_SHADER\n"
2244 "\n"
2245 "#ifdef USEFOG\n"
2246 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2247 "{\n"
2248 "       float fogfrac;\n"
2249 "#ifdef USEFOGHEIGHTTEXTURE\n"
2250 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2251 "       fogfrac = fogheightpixel.a;\n"
2252 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2253 "#else\n"
2254 "# ifdef USEFOGOUTSIDE\n"
2255 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2256 "# else\n"
2257 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2258 "# endif\n"
2259 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2260 "#endif\n"
2261 "}\n"
2262 "#endif\n"
2263 "\n"
2264 "#ifdef USEOFFSETMAPPING\n"
2265 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2266 "{\n"
2267 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2268 "       // 14 sample relief mapping: linear search and then binary search\n"
2269 "       // this basically steps forward a small amount repeatedly until it finds\n"
2270 "       // itself inside solid, then jitters forward and back using decreasing\n"
2271 "       // amounts to find the impact\n"
2272 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2273 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2274 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2275 "       float3 RT = float3(TexCoord, 1);\n"
2276 "       OffsetVector *= 0.1;\n"
2277 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2278 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2279 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2280 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2281 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2282 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2283 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2284 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2285 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2286 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2287 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2288 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2289 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2290 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2291 "       return RT.xy;\n"
2292 "#else\n"
2293 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2294 "       // this basically moves forward the full distance, and then backs up based\n"
2295 "       // on height of samples\n"
2296 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2297 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2298 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2299 "       TexCoord += OffsetVector;\n"
2300 "       OffsetVector *= 0.333;\n"
2301 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2302 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2303 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2304 "       return TexCoord;\n"
2305 "#endif\n"
2306 "}\n"
2307 "#endif // USEOFFSETMAPPING\n"
2308 "\n"
2309 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2310 "#if defined(USESHADOWMAP2D)\n"
2311 "# ifdef USESHADOWMAPORTHO\n"
2312 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2313 "# else\n"
2314 "#  ifdef USESHADOWMAPVSDCT\n"
2315 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2316 "{\n"
2317 "       float3 adir = abs(dir);\n"
2318 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2319 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2320 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2321 "}\n"
2322 "#  else\n"
2323 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2324 "{\n"
2325 "       float3 adir = abs(dir);\n"
2326 "       float ma = adir.z;\n"
2327 "       float4 proj = float4(dir, 2.5);\n"
2328 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2329 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2330 "#ifdef HLSL\n"
2331 "       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"
2332 "#else\n"
2333 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2334 "       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"
2335 "#endif\n"
2336 "}\n"
2337 "#  endif\n"
2338 "# endif\n"
2339 "#endif // defined(USESHADOWMAP2D)\n"
2340 "\n"
2341 "# ifdef USESHADOWMAP2D\n"
2342 "#ifdef USESHADOWMAPVSDCT\n"
2343 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2344 "#else\n"
2345 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2346 "#endif\n"
2347 "{\n"
2348 "#ifdef USESHADOWMAPVSDCT\n"
2349 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2350 "#else\n"
2351 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2352 "#endif\n"
2353 "       float f;\n"
2354 "\n"
2355 "#  ifdef USESHADOWSAMPLER\n"
2356 "#    ifdef USESHADOWMAPPCF\n"
2357 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2358 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2359 "       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"
2360 "#    else\n"
2361 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2362 "#    endif\n"
2363 "#  else\n"
2364 "#    ifdef USESHADOWMAPPCF\n"
2365 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2366 "#      ifdef GL_ARB_texture_gather\n"
2367 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2368 "#      else\n"
2369 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2370 "#      endif\n"
2371 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2372 "#      if USESHADOWMAPPCF > 1\n"
2373 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2374 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2375 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2376 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2377 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2378 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2379 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2380 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2381 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2382 "       float4 locols = float4(group1.ab, group3.ab);\n"
2383 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2384 "       locols.yz += group2.ab;\n"
2385 "       hicols.yz += group8.rg;\n"
2386 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2387 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2388 "                               lerp(locols, hicols, offset.y);\n"
2389 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2390 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2391 "       f = dot(cols, float4(1.0/25.0));\n"
2392 "#      else\n"
2393 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2394 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2395 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2396 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2397 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2398 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2399 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2400 "#      endif\n"
2401 "#     else\n"
2402 "#      ifdef GL_EXT_gpu_shader4\n"
2403 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2404 "#      else\n"
2405 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2406 "#      endif\n"
2407 "#      if USESHADOWMAPPCF > 1\n"
2408 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2409 "       center *= ShadowMap_TextureScale;\n"
2410 "       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"
2411 "       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"
2412 "       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"
2413 "       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"
2414 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2415 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2416 "#      else\n"
2417 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2418 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2419 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2420 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2421 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2422 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2423 "#      endif\n"
2424 "#     endif\n"
2425 "#    else\n"
2426 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2427 "#    endif\n"
2428 "#  endif\n"
2429 "#  ifdef USESHADOWMAPORTHO\n"
2430 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2431 "#  else\n"
2432 "       return f;\n"
2433 "#  endif\n"
2434 "}\n"
2435 "# endif\n"
2436 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2437 "#endif // FRAGMENT_SHADER\n"
2438 "\n"
2439 "\n"
2440 "\n"
2441 "\n"
2442 "#ifdef MODE_DEFERREDGEOMETRY\n"
2443 "#ifdef VERTEX_SHADER\n"
2444 "void main\n"
2445 "(\n"
2446 "float4 gl_Vertex : POSITION,\n"
2447 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2448 "#ifdef USEVERTEXTEXTUREBLEND\n"
2449 "float4 gl_Color : COLOR0,\n"
2450 "#endif\n"
2451 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2452 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2453 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2454 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2455 "uniform float4x4 TexMatrix : register(c0),\n"
2456 "#ifdef USEVERTEXTEXTUREBLEND\n"
2457 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2458 "#endif\n"
2459 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2460 "#ifdef USEOFFSETMAPPING\n"
2461 "uniform float3 EyePosition : register(c24),\n"
2462 "#endif\n"
2463 "out float4 gl_Position : POSITION,\n"
2464 "out float4 gl_FrontColor : COLOR,\n"
2465 "out float4 TexCoordBoth : TEXCOORD0,\n"
2466 "#ifdef USEOFFSETMAPPING\n"
2467 "out float3 EyeVector : TEXCOORD2,\n"
2468 "#endif\n"
2469 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2470 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2471 "out float3 VectorR : TEXCOORD7 // direction of R texcoord (surface normal)\n"
2472 ")\n"
2473 "{\n"
2474 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2475 "#ifdef USEVERTEXTEXTUREBLEND\n"
2476 "#ifdef HLSL\n"
2477 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2478 "#else\n"
2479 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2480 "#endif\n"
2481 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2482 "#endif\n"
2483 "\n"
2484 "       // transform unnormalized eye direction into tangent space\n"
2485 "#ifdef USEOFFSETMAPPING\n"
2486 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2487 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2488 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2489 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2490 "#endif\n"
2491 "\n"
2492 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2493 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2494 "       VectorR = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2495 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2496 "}\n"
2497 "#endif // VERTEX_SHADER\n"
2498 "\n"
2499 "#ifdef FRAGMENT_SHADER\n"
2500 "void main\n"
2501 "(\n"
2502 "float4 TexCoordBoth : TEXCOORD0,\n"
2503 "float3 EyeVector : TEXCOORD2,\n"
2504 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2505 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2506 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2507 "uniform sampler Texture_Normal : register(s0),\n"
2508 "#ifdef USEALPHAKILL\n"
2509 "uniform sampler Texture_Color : register(s1),\n"
2510 "#endif\n"
2511 "uniform sampler Texture_Gloss : register(s2),\n"
2512 "#ifdef USEVERTEXTEXTUREBLEND\n"
2513 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2514 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2515 "#endif\n"
2516 "#ifdef USEOFFSETMAPPING\n"
2517 "uniform float OffsetMapping_Scale : register(c24),\n"
2518 "#endif\n"
2519 "uniform half SpecularPower : register(c36),\n"
2520 "out float4 gl_FragColor : COLOR\n"
2521 ")\n"
2522 "{\n"
2523 "       float2 TexCoord = TexCoordBoth.xy;\n"
2524 "#ifdef USEOFFSETMAPPING\n"
2525 "       // apply offsetmapping\n"
2526 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2527 "#define TexCoord TexCoordOffset\n"
2528 "#endif\n"
2529 "\n"
2530 "#ifdef USEALPHAKILL\n"
2531 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2532 "               discard;\n"
2533 "#endif\n"
2534 "\n"
2535 "#ifdef USEVERTEXTEXTUREBLEND\n"
2536 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2537 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2538 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2539 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2540 "#endif\n"
2541 "\n"
2542 "#ifdef USEVERTEXTEXTUREBLEND\n"
2543 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2544 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2545 "#else\n"
2546 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2547 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2548 "#endif\n"
2549 "\n"
2550 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2551 "}\n"
2552 "#endif // FRAGMENT_SHADER\n"
2553 "#else // !MODE_DEFERREDGEOMETRY\n"
2554 "\n"
2555 "\n"
2556 "\n"
2557 "\n"
2558 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2559 "#ifdef VERTEX_SHADER\n"
2560 "void main\n"
2561 "(\n"
2562 "float4 gl_Vertex : POSITION,\n"
2563 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2564 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2565 "out float4 gl_Position : POSITION,\n"
2566 "out float4 ModelViewPosition : TEXCOORD0\n"
2567 ")\n"
2568 "{\n"
2569 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2570 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2571 "}\n"
2572 "#endif // VERTEX_SHADER\n"
2573 "\n"
2574 "#ifdef FRAGMENT_SHADER\n"
2575 "void main\n"
2576 "(\n"
2577 "#ifdef HLSL\n"
2578 "float2 Pixel : VPOS,\n"
2579 "#else\n"
2580 "float2 Pixel : WPOS,\n"
2581 "#endif\n"
2582 "float4 ModelViewPosition : TEXCOORD0,\n"
2583 "uniform float4x4 ViewToLight : register(c44),\n"
2584 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2585 "uniform float3 LightPosition : register(c23),\n"
2586 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2587 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2588 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2589 "#ifdef USESPECULAR\n"
2590 "uniform half3 DeferredColor_Specular : register(c11),\n"
2591 "uniform half SpecularPower : register(c36),\n"
2592 "#endif\n"
2593 "uniform sampler Texture_Attenuation : register(s9),\n"
2594 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2595 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2596 "\n"
2597 "#ifdef USECUBEFILTER\n"
2598 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2599 "#endif\n"
2600 "\n"
2601 "#ifdef USESHADOWMAP2D\n"
2602 "# ifdef USESHADOWSAMPLER\n"
2603 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2604 "# else\n"
2605 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2606 "# endif\n"
2607 "#endif\n"
2608 "\n"
2609 "#ifdef USESHADOWMAPVSDCT\n"
2610 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2611 "#endif\n"
2612 "\n"
2613 "#if defined(USESHADOWMAP2D)\n"
2614 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2615 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2616 "#endif\n"
2617 "\n"
2618 "out float4 gl_FragData0 : COLOR0,\n"
2619 "out float4 gl_FragData1 : COLOR1\n"
2620 ")\n"
2621 "{\n"
2622 "       // calculate viewspace pixel position\n"
2623 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2624 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2625 "       float3 position;\n"
2626 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2627 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2628 "       // decode viewspace pixel normal\n"
2629 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2630 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2631 "       // surfacenormal = pixel normal in viewspace\n"
2632 "       // LightVector = pixel to light in viewspace\n"
2633 "       // CubeVector = position in lightspace\n"
2634 "       // eyevector = pixel to view in viewspace\n"
2635 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2636 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2637 "#ifdef USEDIFFUSE\n"
2638 "       // calculate diffuse shading\n"
2639 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2640 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2641 "#endif\n"
2642 "#ifdef USESPECULAR\n"
2643 "       // calculate directional shading\n"
2644 "       float3 eyevector = position * -1.0;\n"
2645 "#  ifdef USEEXACTSPECULARMATH\n"
2646 "       half specular = pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
2647 "#  else\n"
2648 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2649 "       half specular = pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
2650 "#  endif\n"
2651 "#endif\n"
2652 "\n"
2653 "#if defined(USESHADOWMAP2D)\n"
2654 "       fade *= ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2655 "#ifdef USESHADOWMAPVSDCT\n"
2656 ", Texture_CubeProjection\n"
2657 "#endif\n"
2658 "       );\n"
2659 "#endif\n"
2660 "\n"
2661 "#ifdef USEDIFFUSE\n"
2662 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2663 "#else\n"
2664 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2665 "#endif\n"
2666 "#ifdef USESPECULAR\n"
2667 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2668 "#else\n"
2669 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2670 "#endif\n"
2671 "\n"
2672 "# ifdef USECUBEFILTER\n"
2673 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2674 "       gl_FragData0.rgb *= cubecolor;\n"
2675 "       gl_FragData1.rgb *= cubecolor;\n"
2676 "# endif\n"
2677 "}\n"
2678 "#endif // FRAGMENT_SHADER\n"
2679 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2680 "\n"
2681 "\n"
2682 "\n"
2683 "\n"
2684 "#ifdef VERTEX_SHADER\n"
2685 "void main\n"
2686 "(\n"
2687 "float4 gl_Vertex : POSITION,\n"
2688 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2689 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2690 "float4 gl_Color : COLOR0,\n"
2691 "#endif\n"
2692 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2693 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2694 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2695 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2696 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2697 "\n"
2698 "uniform float3 EyePosition : register(c24),\n"
2699 "uniform float4x4 TexMatrix : register(c0),\n"
2700 "#ifdef USEVERTEXTEXTUREBLEND\n"
2701 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2702 "#endif\n"
2703 "#ifdef MODE_LIGHTSOURCE\n"
2704 "uniform float4x4 ModelToLight : register(c20),\n"
2705 "#endif\n"
2706 "#ifdef MODE_LIGHTSOURCE\n"
2707 "uniform float3 LightPosition : register(c27),\n"
2708 "#endif\n"
2709 "#ifdef MODE_LIGHTDIRECTION\n"
2710 "uniform float3 LightDir : register(c26),\n"
2711 "#endif\n"
2712 "uniform float4 FogPlane : register(c25),\n"
2713 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2714 "uniform float3 LightPosition : register(c27),\n"
2715 "#endif\n"
2716 "#ifdef USESHADOWMAPORTHO\n"
2717 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2718 "#endif\n"
2719 "\n"
2720 "out float4 gl_FrontColor : COLOR,\n"
2721 "out float4 TexCoordBoth : TEXCOORD0,\n"
2722 "#ifdef USELIGHTMAP\n"
2723 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2724 "#endif\n"
2725 "#ifdef USEEYEVECTOR\n"
2726 "out float3 EyeVector : TEXCOORD2,\n"
2727 "#endif\n"
2728 "#ifdef USEREFLECTION\n"
2729 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2730 "#endif\n"
2731 "#ifdef USEFOG\n"
2732 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2733 "#endif\n"
2734 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2735 "out float3 LightVector : TEXCOORD1,\n"
2736 "#endif\n"
2737 "#ifdef MODE_LIGHTSOURCE\n"
2738 "out float3 CubeVector : TEXCOORD3,\n"
2739 "#endif\n"
2740 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2741 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2742 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2743 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2744 "#endif\n"
2745 "#ifdef USESHADOWMAPORTHO\n"
2746 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2747 "#endif\n"
2748 "out float4 gl_Position : POSITION\n"
2749 ")\n"
2750 "{\n"
2751 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2752 "#ifdef HLSL\n"
2753 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2754 "#else\n"
2755 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2756 "#endif\n"
2757 "#endif\n"
2758 "       // copy the surface texcoord\n"
2759 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2760 "#ifdef USEVERTEXTEXTUREBLEND\n"
2761 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2762 "#endif\n"
2763 "#ifdef USELIGHTMAP\n"
2764 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2765 "#endif\n"
2766 "\n"
2767 "#ifdef MODE_LIGHTSOURCE\n"
2768 "       // transform vertex position into light attenuation/cubemap space\n"
2769 "       // (-1 to +1 across the light box)\n"
2770 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2771 "\n"
2772 "# ifdef USEDIFFUSE\n"
2773 "       // transform unnormalized light direction into tangent space\n"
2774 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2775 "       //  normalize it per pixel)\n"
2776 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2777 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2778 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2779 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2780 "# endif\n"
2781 "#endif\n"
2782 "\n"
2783 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2784 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2785 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2786 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2787 "#endif\n"
2788 "\n"
2789 "       // transform unnormalized eye direction into tangent space\n"
2790 "#ifdef USEEYEVECTOR\n"
2791 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2792 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2793 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2794 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2795 "#endif\n"
2796 "\n"
2797 "#ifdef USEFOG\n"
2798 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2799 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2800 "#endif\n"
2801 "\n"
2802 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2803 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2804 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2805 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2806 "#endif\n"
2807 "\n"
2808 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2809 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2810 "\n"
2811 "#ifdef USESHADOWMAPORTHO\n"
2812 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2813 "#endif\n"
2814 "\n"
2815 "#ifdef USEREFLECTION\n"
2816 "       ModelViewProjectionPosition = gl_Position;\n"
2817 "#endif\n"
2818 "}\n"
2819 "#endif // VERTEX_SHADER\n"
2820 "\n"
2821 "\n"
2822 "\n"
2823 "\n"
2824 "#ifdef FRAGMENT_SHADER\n"
2825 "void main\n"
2826 "(\n"
2827 "#ifdef USEDEFERREDLIGHTMAP\n"
2828 "#ifdef HLSL\n"
2829 "float2 Pixel : VPOS,\n"
2830 "#else\n"
2831 "float2 Pixel : WPOS,\n"
2832 "#endif\n"
2833 "#endif\n"
2834 "float4 gl_FrontColor : COLOR,\n"
2835 "float4 TexCoordBoth : TEXCOORD0,\n"
2836 "#ifdef USELIGHTMAP\n"
2837 "float2 TexCoordLightmap : TEXCOORD1,\n"
2838 "#endif\n"
2839 "#ifdef USEEYEVECTOR\n"
2840 "float3 EyeVector : TEXCOORD2,\n"
2841 "#endif\n"
2842 "#ifdef USEREFLECTION\n"
2843 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2844 "#endif\n"
2845 "#ifdef USEFOG\n"
2846 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2847 "#endif\n"
2848 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2849 "float3 LightVector : TEXCOORD1,\n"
2850 "#endif\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "float3 CubeVector : TEXCOORD3,\n"
2853 "#endif\n"
2854 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2855 "float4 ModelViewPosition : TEXCOORD0,\n"
2856 "#endif\n"
2857 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2858 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2859 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2860 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2861 "#endif\n"
2862 "#ifdef USESHADOWMAPORTHO\n"
2863 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2864 "#endif\n"
2865 "\n"
2866 "uniform sampler Texture_Normal : register(s0),\n"
2867 "uniform sampler Texture_Color : register(s1),\n"
2868 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2869 "uniform sampler Texture_Gloss : register(s2),\n"
2870 "#endif\n"
2871 "#ifdef USEGLOW\n"
2872 "uniform sampler Texture_Glow : register(s3),\n"
2873 "#endif\n"
2874 "#ifdef USEVERTEXTEXTUREBLEND\n"
2875 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2876 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2877 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2878 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2879 "#endif\n"
2880 "#ifdef USEGLOW\n"
2881 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2882 "#endif\n"
2883 "#endif\n"
2884 "#ifdef USECOLORMAPPING\n"
2885 "uniform sampler Texture_Pants : register(s4),\n"
2886 "uniform sampler Texture_Shirt : register(s7),\n"
2887 "#endif\n"
2888 "#ifdef USEFOG\n"
2889 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2890 "uniform sampler Texture_FogMask : register(s8),\n"
2891 "#endif\n"
2892 "#ifdef USELIGHTMAP\n"
2893 "uniform sampler Texture_Lightmap : register(s9),\n"
2894 "#endif\n"
2895 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2896 "uniform sampler Texture_Deluxemap : register(s10),\n"
2897 "#endif\n"
2898 "#ifdef USEREFLECTION\n"
2899 "uniform sampler Texture_Reflection : register(s7),\n"
2900 "#endif\n"
2901 "\n"
2902 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2903 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2904 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2905 "#endif\n"
2906 "#ifdef USEDEFERREDLIGHTMAP\n"
2907 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2908 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2909 "#endif\n"
2910 "\n"
2911 "#ifdef USECOLORMAPPING\n"
2912 "uniform half3 Color_Pants : register(c7),\n"
2913 "uniform half3 Color_Shirt : register(c8),\n"
2914 "#endif\n"
2915 "#ifdef USEFOG\n"
2916 "uniform float3 FogColor : register(c16),\n"
2917 "uniform float FogRangeRecip : register(c20),\n"
2918 "uniform float FogPlaneViewDist : register(c19),\n"
2919 "uniform float FogHeightFade : register(c17),\n"
2920 "#endif\n"
2921 "\n"
2922 "#ifdef USEOFFSETMAPPING\n"
2923 "uniform float OffsetMapping_Scale : register(c24),\n"
2924 "#endif\n"
2925 "\n"
2926 "#ifdef USEDEFERREDLIGHTMAP\n"
2927 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2928 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
2929 "uniform half3 DeferredMod_Specular : register(c13),\n"
2930 "#endif\n"
2931 "uniform half3 Color_Ambient : register(c3),\n"
2932 "uniform half3 Color_Diffuse : register(c4),\n"
2933 "uniform half3 Color_Specular : register(c5),\n"
2934 "uniform half SpecularPower : register(c36),\n"
2935 "#ifdef USEGLOW\n"
2936 "uniform half3 Color_Glow : register(c6),\n"
2937 "#endif\n"
2938 "uniform half Alpha : register(c0),\n"
2939 "#ifdef USEREFLECTION\n"
2940 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2941 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2942 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2943 "uniform half4 ReflectColor : register(c26),\n"
2944 "#endif\n"
2945 "#ifdef USEREFLECTCUBE\n"
2946 "uniform float4x4 ModelToReflectCube : register(c48),\n"
2947 "uniform sampler Texture_ReflectMask : register(s5),\n"
2948 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
2949 "#endif\n"
2950 "#ifdef MODE_LIGHTDIRECTION\n"
2951 "uniform half3 LightColor : register(c21),\n"
2952 "#endif\n"
2953 "#ifdef MODE_LIGHTSOURCE\n"
2954 "uniform half3 LightColor : register(c21),\n"
2955 "#endif\n"
2956 "\n"
2957 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
2958 "uniform sampler Texture_Attenuation : register(s9),\n"
2959 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2960 "#endif\n"
2961 "\n"
2962 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2963 "\n"
2964 "#ifdef USESHADOWMAP2D\n"
2965 "# ifdef USESHADOWSAMPLER\n"
2966 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2967 "# else\n"
2968 "uniform sampler Texture_ShadowMap2D : register(s11),\n"
2969 "# endif\n"
2970 "#endif\n"
2971 "\n"
2972 "#ifdef USESHADOWMAPVSDCT\n"
2973 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2974 "#endif\n"
2975 "\n"
2976 "#if defined(USESHADOWMAP2D)\n"
2977 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2978 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2979 "#endif\n"
2980 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2981 "\n"
2982 "out float4 gl_FragColor : COLOR\n"
2983 ")\n"
2984 "{\n"
2985 "       float2 TexCoord = TexCoordBoth.xy;\n"
2986 "#ifdef USEVERTEXTEXTUREBLEND\n"
2987 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
2988 "#endif\n"
2989 "#ifdef USEOFFSETMAPPING\n"
2990 "       // apply offsetmapping\n"
2991 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2992 "#define TexCoord TexCoordOffset\n"
2993 "#endif\n"
2994 "\n"
2995 "       // combine the diffuse textures (base, pants, shirt)\n"
2996 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
2997 "#ifdef USEALPHAKILL\n"
2998 "       if (color.a < 0.5)\n"
2999 "               discard;\n"
3000 "#endif\n"
3001 "       color.a *= Alpha;\n"
3002 "#ifdef USECOLORMAPPING\n"
3003 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3004 "#endif\n"
3005 "#ifdef USEVERTEXTEXTUREBLEND\n"
3006 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3007 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3008 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3009 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3010 "       color.a = 1.0;\n"
3011 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3012 "#endif\n"
3013 "\n"
3014 "       // get the surface normal\n"
3015 "#ifdef USEVERTEXTEXTUREBLEND\n"
3016 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3017 "#else\n"
3018 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3019 "#endif\n"
3020 "\n"
3021 "       // get the material colors\n"
3022 "       half3 diffusetex = color.rgb;\n"
3023 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3024 "# ifdef USEVERTEXTEXTUREBLEND\n"
3025 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3026 "# else\n"
3027 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3028 "# endif\n"
3029 "#endif\n"
3030 "\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3033 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3034 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3035 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3036 "#endif\n"
3037 "\n"
3038 "\n"
3039 "\n"
3040 "\n"
3041 "#ifdef MODE_LIGHTSOURCE\n"
3042 "       // light source\n"
3043 "#ifdef USEDIFFUSE\n"
3044 "       half3 lightnormal = half3(normalize(LightVector));\n"
3045 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3046 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3047 "#ifdef USESPECULAR\n"
3048 "#ifdef USEEXACTSPECULARMATH\n"
3049 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3050 "#else\n"
3051 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3052 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3053 "#endif\n"
3054 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3055 "#endif\n"
3056 "#else\n"
3057 "       color.rgb = diffusetex * Color_Ambient;\n"
3058 "#endif\n"
3059 "       color.rgb *= LightColor;\n"
3060 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3061 "#if defined(USESHADOWMAP2D)\n"
3062 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3063 "#ifdef USESHADOWMAPVSDCT\n"
3064 ", Texture_CubeProjection\n"
3065 "#endif\n"
3066 "       ));\n"
3067 "\n"
3068 "#endif\n"
3069 "# ifdef USECUBEFILTER\n"
3070 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3071 "# endif\n"
3072 "\n"
3073 "#ifdef USESHADOWMAP2D\n"
3074 "#ifdef USESHADOWMAPVSDCT\n"
3075 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3076 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale).rgb);\n"
3077 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3078 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection).xy * ShadowMap_TextureScale));\n"
3079 "#else\n"
3080 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3081 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3082 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale).rgb);\n"
3083 "//     color.rgb = half3(GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xyz * float3(ShadowMap_TextureScale,1.0));\n"
3084 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, GetShadowMapTC2D(CubeVector, ShadowMap_Parameters).xy * ShadowMap_TextureScale));\n"
3085 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3086 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3087 "//     color.r = half(shadowmaptc.z);\n"
3088 "#endif\n"
3089 "//     color.r = 1;\n"
3090 "#endif\n"
3091 "//     color.rgb = half3(1,1,1);\n"
3092 "#endif // MODE_LIGHTSOURCE\n"
3093 "\n"
3094 "\n"
3095 "\n"
3096 "\n"
3097 "#ifdef MODE_LIGHTDIRECTION\n"
3098 "#define SHADING\n"
3099 "#ifdef USEDIFFUSE\n"
3100 "       half3 lightnormal = half3(normalize(LightVector));\n"
3101 "#endif\n"
3102 "#define lightcolor LightColor\n"
3103 "#endif // MODE_LIGHTDIRECTION\n"
3104 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3105 "#define SHADING\n"
3106 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3107 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3108 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3109 "       // convert modelspace light vector to tangentspace\n"
3110 "       half3 lightnormal;\n"
3111 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3112 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3113 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3114 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3115 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3116 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3117 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3118 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3119 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3120 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3121 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3122 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3123 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3124 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3125 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3126 "#define SHADING\n"
3127 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3128 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3129 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3130 "#endif\n"
3131 "\n"
3132 "\n"
3133 "\n"
3134 "\n"
3135 "#ifdef MODE_LIGHTMAP\n"
3136 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3137 "#endif // MODE_LIGHTMAP\n"
3138 "#ifdef MODE_VERTEXCOLOR\n"
3139 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3140 "#endif // MODE_VERTEXCOLOR\n"
3141 "#ifdef MODE_FLATCOLOR\n"
3142 "       color.rgb = diffusetex * Color_Ambient;\n"
3143 "#endif // MODE_FLATCOLOR\n"
3144 "\n"
3145 "\n"
3146 "\n"
3147 "\n"
3148 "#ifdef SHADING\n"
3149 "# ifdef USEDIFFUSE\n"
3150 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3151 "#  ifdef USESPECULAR\n"
3152 "#   ifdef USEEXACTSPECULARMATH\n"
3153 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3154 "#   else\n"
3155 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3156 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3157 "#   endif\n"
3158 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3159 "#  else\n"
3160 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3161 "#  endif\n"
3162 "# else\n"
3163 "       color.rgb = diffusetex * Color_Ambient;\n"
3164 "# endif\n"
3165 "#endif\n"
3166 "\n"
3167 "#ifdef USESHADOWMAPORTHO\n"
3168 "       color.rgb *= ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale);\n"
3169 "#endif\n"
3170 "\n"
3171 "#ifdef USEDEFERREDLIGHTMAP\n"
3172 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3173 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3174 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3175 "#endif\n"
3176 "\n"
3177 "#ifdef USEGLOW\n"
3178 "#ifdef USEVERTEXTEXTUREBLEND\n"
3179 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3180 "#else\n"
3181 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3182 "#endif\n"
3183 "#endif\n"
3184 "\n"
3185 "#ifdef USEFOG\n"
3186 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3187 "#endif\n"
3188 "\n"
3189 "       // 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"
3190 "#ifdef USEREFLECTION\n"
3191 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3192 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3193 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3194 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3195 "       // FIXME temporary hack to detect the case that the reflection\n"
3196 "       // gets blackened at edges due to leaving the area that contains actual\n"
3197 "       // content.\n"
3198 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3199 "       // 'appening.\n"
3200 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3201 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3202 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3203 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3204 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3205 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3206 "#endif\n"
3207 "\n"
3208 "       gl_FragColor = float4(color);\n"
3209 "}\n"
3210 "#endif // FRAGMENT_SHADER\n"
3211 "\n"
3212 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3213 "#endif // !MODE_DEFERREDGEOMETRY\n"
3214 "#endif // !MODE_WATER\n"
3215 "#endif // !MODE_REFRACTION\n"
3216 "#endif // !MODE_BLOOMBLUR\n"
3217 "#endif // !MODE_GENERIC\n"
3218 "#endif // !MODE_POSTPROCESS\n"
3219 "#endif // !MODE_SHOWDEPTH\n"
3220 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3221 ;
3222
3223 char *glslshaderstring = NULL;
3224 char *cgshaderstring = NULL;
3225 char *hlslshaderstring = NULL;
3226
3227 //=======================================================================================================================================================
3228
3229 typedef struct shaderpermutationinfo_s
3230 {
3231         const char *pretext;
3232         const char *name;
3233 }
3234 shaderpermutationinfo_t;
3235
3236 typedef struct shadermodeinfo_s
3237 {
3238         const char *vertexfilename;
3239         const char *geometryfilename;
3240         const char *fragmentfilename;
3241         const char *pretext;
3242         const char *name;
3243 }
3244 shadermodeinfo_t;
3245
3246 typedef enum shaderpermutation_e
3247 {
3248         SHADERPERMUTATION_DIFFUSE = 1<<0, ///< (lightsource) whether to use directional shading
3249         SHADERPERMUTATION_VERTEXTEXTUREBLEND = 1<<1, ///< indicates this is a two-layer material blend based on vertex alpha (q3bsp)
3250         SHADERPERMUTATION_VIEWTINT = 1<<2, ///< view tint (postprocessing only)
3251         SHADERPERMUTATION_COLORMAPPING = 1<<3, ///< indicates this is a colormapped skin
3252         SHADERPERMUTATION_SATURATION = 1<<4, ///< saturation (postprocessing only)
3253         SHADERPERMUTATION_FOGINSIDE = 1<<5, ///< tint the color by fog color or black if using additive blend mode
3254         SHADERPERMUTATION_FOGOUTSIDE = 1<<6, ///< tint the color by fog color or black if using additive blend mode
3255         SHADERPERMUTATION_FOGHEIGHTTEXTURE = 1<<7, ///< fog color and density determined by texture mapped on vertical axis
3256         SHADERPERMUTATION_GAMMARAMPS = 1<<8, ///< gamma (postprocessing only)
3257         SHADERPERMUTATION_CUBEFILTER = 1<<9, ///< (lightsource) use cubemap light filter
3258         SHADERPERMUTATION_GLOW = 1<<10, ///< (lightmap) blend in an additive glow texture
3259         SHADERPERMUTATION_BLOOM = 1<<11, ///< bloom (postprocessing only)
3260         SHADERPERMUTATION_SPECULAR = 1<<12, ///< (lightsource or deluxemapping) render specular effects
3261         SHADERPERMUTATION_POSTPROCESSING = 1<<13, ///< user defined postprocessing (postprocessing only)
3262         SHADERPERMUTATION_EXACTSPECULARMATH = 1<<14, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3263         SHADERPERMUTATION_REFLECTION = 1<<15, ///< normalmap-perturbed reflection of the scene infront of the surface, preformed as an overlay on the surface
3264         SHADERPERMUTATION_OFFSETMAPPING = 1<<16, ///< adjust texcoords to roughly simulate a displacement mapped surface
3265         SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING = 1<<17, ///< adjust texcoords to accurately simulate a displacement mapped surface (requires OFFSETMAPPING to also be set!)
3266         SHADERPERMUTATION_SHADOWMAP2D = 1<<18, ///< (lightsource) use shadowmap texture as light filter
3267         SHADERPERMUTATION_SHADOWMAPPCF = 1<<19, ///< (lightsource) use percentage closer filtering on shadowmap test results
3268         SHADERPERMUTATION_SHADOWMAPPCF2 = 1<<20, ///< (lightsource) use higher quality percentage closer filtering on shadowmap test results
3269         SHADERPERMUTATION_SHADOWSAMPLER = 1<<21, ///< (lightsource) use hardware shadowmap test
3270         SHADERPERMUTATION_SHADOWMAPVSDCT = 1<<22, ///< (lightsource) use virtual shadow depth cube texture for shadowmap indexing
3271         SHADERPERMUTATION_SHADOWMAPORTHO = 1<<23, //< (lightsource) use orthographic shadowmap projection
3272         SHADERPERMUTATION_DEFERREDLIGHTMAP = 1<<24, ///< (lightmap) read Texture_ScreenDiffuse/Specular textures and add them on top of lightmapping
3273         SHADERPERMUTATION_ALPHAKILL = 1<<25, ///< (deferredgeometry) discard pixel if diffuse texture alpha below 0.5
3274         SHADERPERMUTATION_REFLECTCUBE = 1<<26, ///< fake reflections using global cubemap (not HDRI light probe)
3275         SHADERPERMUTATION_LIMIT = 1<<27, ///< size of permutations array
3276         SHADERPERMUTATION_COUNT = 27 ///< size of shaderpermutationinfo array
3277 }
3278 shaderpermutation_t;
3279
3280 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3281 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3282 {
3283         {"#define USEDIFFUSE\n", " diffuse"},
3284         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3285         {"#define USEVIEWTINT\n", " viewtint"},
3286         {"#define USECOLORMAPPING\n", " colormapping"},
3287         {"#define USESATURATION\n", " saturation"},
3288         {"#define USEFOGINSIDE\n", " foginside"},
3289         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3290         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3291         {"#define USEGAMMARAMPS\n", " gammaramps"},
3292         {"#define USECUBEFILTER\n", " cubefilter"},
3293         {"#define USEGLOW\n", " glow"},
3294         {"#define USEBLOOM\n", " bloom"},
3295         {"#define USESPECULAR\n", " specular"},
3296         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3297         {"#define USEEXACTSPECULARMATH\n", " exactspecularmath"},
3298         {"#define USEREFLECTION\n", " reflection"},
3299         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3300         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3301         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3302         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3303         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3304         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3305         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3306         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3307         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3308         {"#define USEALPHAKILL\n", " alphakill"},
3309         {"#define USEREFLECTCUBE\n", " reflectcube"},
3310 };
3311
3312 /// this enum is multiplied by SHADERPERMUTATION_MODEBASE
3313 typedef enum shadermode_e
3314 {
3315         SHADERMODE_GENERIC, ///< (particles/HUD/etc) vertex color, optionally multiplied by one texture
3316         SHADERMODE_POSTPROCESS, ///< postprocessing shader (r_glsl_postprocess)
3317         SHADERMODE_DEPTH_OR_SHADOW, ///< (depthfirst/shadows) vertex shader only
3318         SHADERMODE_FLATCOLOR, ///< (lightmap) modulate texture by uniform color (q1bsp, q3bsp)
3319         SHADERMODE_VERTEXCOLOR, ///< (lightmap) modulate texture by vertex colors (q3bsp)
3320         SHADERMODE_LIGHTMAP, ///< (lightmap) modulate texture by lightmap texture (q1bsp, q3bsp)
3321         SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE, ///< (lightmap) use directional pixel shading from texture containing modelspace light directions (q3bsp deluxemap)
3322         SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE, ///< (lightmap) use directional pixel shading from texture containing tangentspace light directions (q1bsp deluxemap)
3323         SHADERMODE_LIGHTDIRECTION, ///< (lightmap) use directional pixel shading from fixed light direction (q3bsp)
3324         SHADERMODE_LIGHTSOURCE, ///< (lightsource) use directional pixel shading from light source (rtlight)
3325         SHADERMODE_REFRACTION, ///< refract background (the material is rendered normally after this pass)
3326         SHADERMODE_WATER, ///< refract background and reflection (the material is rendered normally after this pass)
3327         SHADERMODE_SHOWDEPTH, ///< (debugging) renders depth as color
3328         SHADERMODE_DEFERREDGEOMETRY, ///< (deferred) render material properties to screenspace geometry buffers
3329         SHADERMODE_DEFERREDLIGHTSOURCE, ///< (deferred) use directional pixel shading from light source (rtlight) on screenspace geometry buffers
3330         SHADERMODE_COUNT
3331 }
3332 shadermode_t;
3333
3334 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3335 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3336 {
3337         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3338         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3339         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3340         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3341         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3342         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3343         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3344         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3345         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3346         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3347         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3348         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3349         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3350         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3351         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3352 };
3353
3354 #ifdef SUPPORTCG
3355 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3356 {
3357         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3358         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3359         {"cg/default.cg", NULL, NULL           , "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3360         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3361         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3362         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3363         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3364         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3365         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3366         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3367         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3368         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3369         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3370         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3371         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3372 };
3373 #endif
3374
3375 #ifdef SUPPORTD3D
3376 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3377 {
3378         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3379         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3380         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth"},
3381         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3382         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3383         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3384         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3385         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3386         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3387         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3388         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3389         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3390         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3391         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3392         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3393 };
3394 #endif
3395
3396 struct r_glsl_permutation_s;
3397 typedef struct r_glsl_permutation_s
3398 {
3399         /// hash lookup data
3400         struct r_glsl_permutation_s *hashnext;
3401         unsigned int mode;
3402         unsigned int permutation;
3403
3404         /// indicates if we have tried compiling this permutation already
3405         qboolean compiled;
3406         /// 0 if compilation failed
3407         int program;
3408         /// locations of detected uniforms in program object, or -1 if not found
3409         int loc_Texture_First;
3410         int loc_Texture_Second;
3411         int loc_Texture_GammaRamps;
3412         int loc_Texture_Normal;
3413         int loc_Texture_Color;
3414         int loc_Texture_Gloss;
3415         int loc_Texture_Glow;
3416         int loc_Texture_SecondaryNormal;
3417         int loc_Texture_SecondaryColor;
3418         int loc_Texture_SecondaryGloss;
3419         int loc_Texture_SecondaryGlow;
3420         int loc_Texture_Pants;
3421         int loc_Texture_Shirt;
3422         int loc_Texture_FogHeightTexture;
3423         int loc_Texture_FogMask;
3424         int loc_Texture_Lightmap;
3425         int loc_Texture_Deluxemap;
3426         int loc_Texture_Attenuation;
3427         int loc_Texture_Cube;
3428         int loc_Texture_Refraction;
3429         int loc_Texture_Reflection;
3430         int loc_Texture_ShadowMap2D;
3431         int loc_Texture_CubeProjection;
3432         int loc_Texture_ScreenDepth;
3433         int loc_Texture_ScreenNormalMap;
3434         int loc_Texture_ScreenDiffuse;
3435         int loc_Texture_ScreenSpecular;
3436         int loc_Texture_ReflectMask;
3437         int loc_Texture_ReflectCube;
3438         int loc_Alpha;
3439         int loc_BloomBlur_Parameters;
3440         int loc_ClientTime;
3441         int loc_Color_Ambient;
3442         int loc_Color_Diffuse;
3443         int loc_Color_Specular;
3444         int loc_Color_Glow;
3445         int loc_Color_Pants;
3446         int loc_Color_Shirt;
3447         int loc_DeferredColor_Ambient;
3448         int loc_DeferredColor_Diffuse;
3449         int loc_DeferredColor_Specular;
3450         int loc_DeferredMod_Diffuse;
3451         int loc_DeferredMod_Specular;
3452         int loc_DistortScaleRefractReflect;
3453         int loc_EyePosition;
3454         int loc_FogColor;
3455         int loc_FogHeightFade;
3456         int loc_FogPlane;
3457         int loc_FogPlaneViewDist;
3458         int loc_FogRangeRecip;
3459         int loc_LightColor;
3460         int loc_LightDir;
3461         int loc_LightPosition;
3462         int loc_OffsetMapping_Scale;
3463         int loc_PixelSize;
3464         int loc_ReflectColor;
3465         int loc_ReflectFactor;
3466         int loc_ReflectOffset;
3467         int loc_RefractColor;
3468         int loc_Saturation;
3469         int loc_ScreenCenterRefractReflect;
3470         int loc_ScreenScaleRefractReflect;
3471         int loc_ScreenToDepth;
3472         int loc_ShadowMap_Parameters;
3473         int loc_ShadowMap_TextureScale;
3474         int loc_SpecularPower;
3475         int loc_UserVec1;
3476         int loc_UserVec2;
3477         int loc_UserVec3;
3478         int loc_UserVec4;
3479         int loc_ViewTintColor;
3480         int loc_ViewToLight;
3481         int loc_ModelToLight;
3482         int loc_TexMatrix;
3483         int loc_BackgroundTexMatrix;
3484         int loc_ModelViewProjectionMatrix;
3485         int loc_ModelViewMatrix;
3486         int loc_PixelToScreenTexCoord;
3487         int loc_ModelToReflectCube;
3488         int loc_ShadowMapMatrix;
3489         int loc_BloomColorSubtract;
3490 }
3491 r_glsl_permutation_t;
3492
3493 #define SHADERPERMUTATION_HASHSIZE 256
3494
3495 /// information about each possible shader permutation
3496 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3497 /// currently selected permutation
3498 r_glsl_permutation_t *r_glsl_permutation;
3499 /// storage for permutations linked in the hash table
3500 memexpandablearray_t r_glsl_permutationarray;
3501
3502 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3503 {
3504         //unsigned int hashdepth = 0;
3505         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3506         r_glsl_permutation_t *p;
3507         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3508         {
3509                 if (p->mode == mode && p->permutation == permutation)
3510                 {
3511                         //if (hashdepth > 10)
3512                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3513                         return p;
3514                 }
3515                 //hashdepth++;
3516         }
3517         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3518         p->mode = mode;
3519         p->permutation = permutation;
3520         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3521         r_glsl_permutationhash[mode][hashindex] = p;
3522         //if (hashdepth > 10)
3523         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3524         return p;
3525 }
3526
3527 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3528 {
3529         char *shaderstring;
3530         if (!filename || !filename[0])
3531                 return NULL;
3532         if (!strcmp(filename, "glsl/default.glsl"))
3533         {
3534                 if (!glslshaderstring)
3535                 {
3536                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3537                         if (glslshaderstring)
3538                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3539                         else
3540                                 glslshaderstring = (char *)builtinshaderstring;
3541                 }
3542                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3543                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3544                 return shaderstring;
3545         }
3546         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3547         if (shaderstring)
3548         {
3549                 if (printfromdisknotice)
3550                         Con_DPrintf("from disk %s... ", filename);
3551                 return shaderstring;
3552         }
3553         return shaderstring;
3554 }
3555
3556 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3557 {
3558         int i;
3559         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3560         int vertstrings_count = 0;
3561         int geomstrings_count = 0;
3562         int fragstrings_count = 0;
3563         char *vertexstring, *geometrystring, *fragmentstring;
3564         const char *vertstrings_list[32+3];
3565         const char *geomstrings_list[32+3];
3566         const char *fragstrings_list[32+3];
3567         char permutationname[256];
3568
3569         if (p->compiled)
3570                 return;
3571         p->compiled = true;
3572         p->program = 0;
3573
3574         permutationname[0] = 0;
3575         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3576         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3577         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3578
3579         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3580
3581         // the first pretext is which type of shader to compile as
3582         // (later these will all be bound together as a program object)
3583         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3584         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3585         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3586
3587         // the second pretext is the mode (for example a light source)
3588         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3589         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3590         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3591         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3592
3593         // now add all the permutation pretexts
3594         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3595         {
3596                 if (permutation & (1<<i))
3597                 {
3598                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3599                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3600                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3601                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3602                 }
3603                 else
3604                 {
3605                         // keep line numbers correct
3606                         vertstrings_list[vertstrings_count++] = "\n";
3607                         geomstrings_list[geomstrings_count++] = "\n";
3608                         fragstrings_list[fragstrings_count++] = "\n";
3609                 }
3610         }
3611
3612         // now append the shader text itself
3613         vertstrings_list[vertstrings_count++] = vertexstring;
3614         geomstrings_list[geomstrings_count++] = geometrystring;
3615         fragstrings_list[fragstrings_count++] = fragmentstring;
3616
3617         // if any sources were NULL, clear the respective list
3618         if (!vertexstring)
3619                 vertstrings_count = 0;
3620         if (!geometrystring)
3621                 geomstrings_count = 0;
3622         if (!fragmentstring)
3623                 fragstrings_count = 0;
3624
3625         // compile the shader program
3626         if (vertstrings_count + geomstrings_count + fragstrings_count)
3627                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3628         if (p->program)
3629         {
3630                 CHECKGLERROR
3631                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3632                 // look up all the uniform variable names we care about, so we don't
3633                 // have to look them up every time we set them
3634
3635                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3636                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3637                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3638                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3639                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3640                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3641                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3642                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3643                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3644                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3645                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3646                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3647                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3648                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3649                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3650                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3651                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3652                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3653                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3654                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3655                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3656                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3657                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3658                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3659                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3660                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3661                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3662                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3663                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3664                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3665                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3666                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3667                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3668                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3669                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3670                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3671                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3672                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3673                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3674                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3675                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3676                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3677                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3678                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3679                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3680                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3681                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3682                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3683                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3684                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3685                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3686                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3687                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3688                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3689                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3690                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3691                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3692                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3693                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3694                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3695                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3696                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3697                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3698                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3699                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3700                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3701                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3702                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3703                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3704                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3705                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3706                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3707                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3708                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3709                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3710                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3711                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3712                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3713                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3714                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3715                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3716                 // initialize the samplers to refer to the texture units we use
3717                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3718                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3719                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3720                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3721                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3722                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3723                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3724                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3725                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3726                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3727                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3728                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3729                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3730                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3731                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3732                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3733                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3734                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3735                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3736                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3737                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3738                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , permutation & SHADERPERMUTATION_SHADOWMAPORTHO ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D);
3739                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3740                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3741                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3742                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3743                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3744                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3745                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3746                 CHECKGLERROR
3747                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3748         }
3749         else
3750                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3751
3752         // free the strings
3753         if (vertexstring)
3754                 Mem_Free(vertexstring);
3755         if (geometrystring)
3756                 Mem_Free(geometrystring);
3757         if (fragmentstring)
3758                 Mem_Free(fragmentstring);
3759 }
3760
3761 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3762 {
3763         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3764         if (r_glsl_permutation != perm)
3765         {
3766                 r_glsl_permutation = perm;
3767                 if (!r_glsl_permutation->program)
3768                 {
3769                         if (!r_glsl_permutation->compiled)
3770                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3771                         if (!r_glsl_permutation->program)
3772                         {
3773                                 // remove features until we find a valid permutation
3774                                 int i;
3775                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3776                                 {
3777                                         // reduce i more quickly whenever it would not remove any bits
3778                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3779                                         if (!(permutation & j))
3780                                                 continue;
3781                                         permutation -= j;
3782                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3783                                         if (!r_glsl_permutation->compiled)
3784                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3785                                         if (r_glsl_permutation->program)
3786                                                 break;
3787                                 }
3788                                 if (i >= SHADERPERMUTATION_COUNT)
3789                                 {
3790                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3791                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3792                                         qglUseProgramObjectARB(0);CHECKGLERROR
3793                                         return; // no bit left to clear, entire mode is broken
3794                                 }
3795                         }
3796                 }
3797                 CHECKGLERROR
3798                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3799         }
3800         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3801         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3802         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3803 }
3804
3805 #ifdef SUPPORTCG
3806 #include <Cg/cgGL.h>
3807 struct r_cg_permutation_s;
3808 typedef struct r_cg_permutation_s
3809 {
3810         /// hash lookup data
3811         struct r_cg_permutation_s *hashnext;
3812         unsigned int mode;
3813         unsigned int permutation;
3814
3815         /// indicates if we have tried compiling this permutation already
3816         qboolean compiled;
3817         /// 0 if compilation failed
3818         CGprogram vprogram;
3819         CGprogram fprogram;
3820         /// locations of detected parameters in programs, or NULL if not found
3821         CGparameter vp_EyePosition;
3822         CGparameter vp_FogPlane;
3823         CGparameter vp_LightDir;
3824         CGparameter vp_LightPosition;
3825         CGparameter vp_ModelToLight;
3826         CGparameter vp_TexMatrix;
3827         CGparameter vp_BackgroundTexMatrix;
3828         CGparameter vp_ModelViewProjectionMatrix;
3829         CGparameter vp_ModelViewMatrix;
3830         CGparameter vp_ShadowMapMatrix;
3831
3832         CGparameter fp_Texture_First;
3833         CGparameter fp_Texture_Second;
3834         CGparameter fp_Texture_GammaRamps;
3835         CGparameter fp_Texture_Normal;
3836         CGparameter fp_Texture_Color;
3837         CGparameter fp_Texture_Gloss;
3838         CGparameter fp_Texture_Glow;
3839         CGparameter fp_Texture_SecondaryNormal;
3840         CGparameter fp_Texture_SecondaryColor;
3841         CGparameter fp_Texture_SecondaryGloss;
3842         CGparameter fp_Texture_SecondaryGlow;
3843         CGparameter fp_Texture_Pants;
3844         CGparameter fp_Texture_Shirt;
3845         CGparameter fp_Texture_FogHeightTexture;
3846         CGparameter fp_Texture_FogMask;
3847         CGparameter fp_Texture_Lightmap;
3848         CGparameter fp_Texture_Deluxemap;
3849         CGparameter fp_Texture_Attenuation;
3850         CGparameter fp_Texture_Cube;
3851         CGparameter fp_Texture_Refraction;
3852         CGparameter fp_Texture_Reflection;
3853         CGparameter fp_Texture_ShadowMap2D;
3854         CGparameter fp_Texture_CubeProjection;
3855         CGparameter fp_Texture_ScreenDepth;
3856         CGparameter fp_Texture_ScreenNormalMap;
3857         CGparameter fp_Texture_ScreenDiffuse;
3858         CGparameter fp_Texture_ScreenSpecular;
3859         CGparameter fp_Texture_ReflectMask;
3860         CGparameter fp_Texture_ReflectCube;
3861         CGparameter fp_Alpha;
3862         CGparameter fp_BloomBlur_Parameters;
3863         CGparameter fp_ClientTime;
3864         CGparameter fp_Color_Ambient;
3865         CGparameter fp_Color_Diffuse;
3866         CGparameter fp_Color_Specular;
3867         CGparameter fp_Color_Glow;
3868         CGparameter fp_Color_Pants;
3869         CGparameter fp_Color_Shirt;
3870         CGparameter fp_DeferredColor_Ambient;
3871         CGparameter fp_DeferredColor_Diffuse;
3872         CGparameter fp_DeferredColor_Specular;
3873         CGparameter fp_DeferredMod_Diffuse;
3874         CGparameter fp_DeferredMod_Specular;
3875         CGparameter fp_DistortScaleRefractReflect;
3876         CGparameter fp_EyePosition;
3877         CGparameter fp_FogColor;
3878         CGparameter fp_FogHeightFade;
3879         CGparameter fp_FogPlane;
3880         CGparameter fp_FogPlaneViewDist;
3881         CGparameter fp_FogRangeRecip;
3882         CGparameter fp_LightColor;
3883         CGparameter fp_LightDir;
3884         CGparameter fp_LightPosition;
3885         CGparameter fp_OffsetMapping_Scale;
3886         CGparameter fp_PixelSize;
3887         CGparameter fp_ReflectColor;
3888         CGparameter fp_ReflectFactor;
3889         CGparameter fp_ReflectOffset;
3890         CGparameter fp_RefractColor;
3891         CGparameter fp_Saturation;
3892         CGparameter fp_ScreenCenterRefractReflect;
3893         CGparameter fp_ScreenScaleRefractReflect;
3894         CGparameter fp_ScreenToDepth;
3895         CGparameter fp_ShadowMap_Parameters;
3896         CGparameter fp_ShadowMap_TextureScale;
3897         CGparameter fp_SpecularPower;
3898         CGparameter fp_UserVec1;
3899         CGparameter fp_UserVec2;
3900         CGparameter fp_UserVec3;
3901         CGparameter fp_UserVec4;
3902         CGparameter fp_ViewTintColor;
3903         CGparameter fp_ViewToLight;
3904         CGparameter fp_PixelToScreenTexCoord;
3905         CGparameter fp_ModelToReflectCube;
3906         CGparameter fp_BloomColorSubtract;
3907 }
3908 r_cg_permutation_t;
3909
3910 /// information about each possible shader permutation
3911 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3912 /// currently selected permutation
3913 r_cg_permutation_t *r_cg_permutation;
3914 /// storage for permutations linked in the hash table
3915 memexpandablearray_t r_cg_permutationarray;
3916
3917 #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));}}
3918
3919 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
3920 {
3921         //unsigned int hashdepth = 0;
3922         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3923         r_cg_permutation_t *p;
3924         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
3925         {
3926                 if (p->mode == mode && p->permutation == permutation)
3927                 {
3928                         //if (hashdepth > 10)
3929                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3930                         return p;
3931                 }
3932                 //hashdepth++;
3933         }
3934         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
3935         p->mode = mode;
3936         p->permutation = permutation;
3937         p->hashnext = r_cg_permutationhash[mode][hashindex];
3938         r_cg_permutationhash[mode][hashindex] = p;
3939         //if (hashdepth > 10)
3940         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3941         return p;
3942 }
3943
3944 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
3945 {
3946         char *shaderstring;
3947         if (!filename || !filename[0])
3948                 return NULL;
3949         if (!strcmp(filename, "cg/default.cg"))
3950         {
3951                 if (!cgshaderstring)
3952                 {
3953                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3954                         if (cgshaderstring)
3955                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3956                         else
3957                                 cgshaderstring = (char *)builtincgshaderstring;
3958                 }
3959                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
3960                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
3961                 return shaderstring;
3962         }
3963         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3964         if (shaderstring)
3965         {
3966                 if (printfromdisknotice)
3967                         Con_DPrintf("from disk %s... ", filename);
3968                 return shaderstring;
3969         }
3970         return shaderstring;
3971 }
3972
3973 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
3974 {
3975         // TODO: load or create .fp and .vp shader files
3976 }
3977
3978 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
3979 {
3980         int i;
3981         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
3982         int vertstrings_count = 0, vertstring_length = 0;
3983         int geomstrings_count = 0, geomstring_length = 0;
3984         int fragstrings_count = 0, fragstring_length = 0;
3985         char *t;
3986         char *vertexstring, *geometrystring, *fragmentstring;
3987         char *vertstring, *geomstring, *fragstring;
3988         const char *vertstrings_list[32+3];
3989         const char *geomstrings_list[32+3];
3990         const char *fragstrings_list[32+3];
3991         char permutationname[256];
3992         char cachename[256];
3993         CGprofile vertexProfile;
3994         CGprofile fragmentProfile;
3995
3996         if (p->compiled)
3997                 return;
3998         p->compiled = true;
3999         p->vprogram = NULL;
4000         p->fprogram = NULL;
4001
4002         permutationname[0] = 0;
4003         cachename[0] = 0;
4004         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4005         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4006         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4007
4008         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4009         strlcat(cachename, "cg/", sizeof(cachename));
4010
4011         // the first pretext is which type of shader to compile as
4012         // (later these will all be bound together as a program object)
4013         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4014         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4015         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4016
4017         // the second pretext is the mode (for example a light source)
4018         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4019         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4020         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4021         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4022         strlcat(cachename, modeinfo->name, sizeof(cachename));
4023
4024         // now add all the permutation pretexts
4025         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4026         {
4027                 if (permutation & (1<<i))
4028                 {
4029                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4030                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4031                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4032                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4033                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4034                 }
4035                 else
4036                 {
4037                         // keep line numbers correct
4038                         vertstrings_list[vertstrings_count++] = "\n";
4039                         geomstrings_list[geomstrings_count++] = "\n";
4040                         fragstrings_list[fragstrings_count++] = "\n";
4041                 }
4042         }
4043
4044         // replace spaces in the cachename with _ characters
4045         for (i = 0;cachename[i];i++)
4046                 if (cachename[i] == ' ')
4047                         cachename[i] = '_';
4048
4049         // now append the shader text itself
4050         vertstrings_list[vertstrings_count++] = vertexstring;
4051         geomstrings_list[geomstrings_count++] = geometrystring;
4052         fragstrings_list[fragstrings_count++] = fragmentstring;
4053
4054         // if any sources were NULL, clear the respective list
4055         if (!vertexstring)
4056                 vertstrings_count = 0;
4057         if (!geometrystring)
4058                 geomstrings_count = 0;
4059         if (!fragmentstring)
4060                 fragstrings_count = 0;
4061
4062         vertstring_length = 0;
4063         for (i = 0;i < vertstrings_count;i++)
4064                 vertstring_length += strlen(vertstrings_list[i]);
4065         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4066         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4067                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4068
4069         geomstring_length = 0;
4070         for (i = 0;i < geomstrings_count;i++)
4071                 geomstring_length += strlen(geomstrings_list[i]);
4072         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4073         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4074                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4075
4076         fragstring_length = 0;
4077         for (i = 0;i < fragstrings_count;i++)
4078                 fragstring_length += strlen(fragstrings_list[i]);
4079         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4080         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4081                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4082
4083         CHECKGLERROR
4084         CHECKCGERROR
4085         //vertexProfile = CG_PROFILE_ARBVP1;
4086         //fragmentProfile = CG_PROFILE_ARBFP1;
4087         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4088         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4089         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4090         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4091         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4092         CHECKGLERROR
4093
4094         // try to load the cached shader, or generate one
4095         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4096
4097         // if caching failed, do a dynamic compile for now
4098         CHECKCGERROR
4099         if (vertstring[0] && !p->vprogram)
4100                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4101         CHECKCGERROR
4102         if (fragstring[0] && !p->fprogram)
4103                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4104         CHECKCGERROR
4105
4106         // look up all the uniform variable names we care about, so we don't
4107         // have to look them up every time we set them
4108         if (p->vprogram)
4109         {
4110                 CHECKCGERROR
4111                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4112                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4113                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4114                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4115                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4116                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4117                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4118                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4119                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4120                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4121                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4122                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4123                 CHECKCGERROR
4124         }
4125         if (p->fprogram)
4126         {
4127                 CHECKCGERROR
4128                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4129                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4130                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4131                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4132                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4133                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4134                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4135                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4136                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4137                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4138                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4139                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4140                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4141                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4142                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4143                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4144                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4145                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4146                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4147                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4148                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4149                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4150                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4151                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4152                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4153                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4154                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4155                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4156                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4157                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4158                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4159                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4160                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4161                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4162                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4163                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4164                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4165                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4166                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4167                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4168                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4169                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4170                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4171                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4172                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4173                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4174                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4175                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4176                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4177                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4178                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4179                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4180                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4181                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4182                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4183                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4184                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4185                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4186                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4187                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4188                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4189                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4190                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4191                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4192                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4193                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4194                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4195                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4196                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4197                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4198                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4199                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4200                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4201                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4202                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4203                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4204                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4205                 CHECKCGERROR
4206         }
4207
4208         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4209                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4210         else
4211                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4212
4213         // free the strings
4214         if (vertstring)
4215                 Mem_Free(vertstring);
4216         if (geomstring)
4217                 Mem_Free(geomstring);
4218         if (fragstring)
4219                 Mem_Free(fragstring);
4220         if (vertexstring)
4221                 Mem_Free(vertexstring);
4222         if (geometrystring)
4223                 Mem_Free(geometrystring);
4224         if (fragmentstring)
4225                 Mem_Free(fragmentstring);
4226 }
4227
4228 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4229 {
4230         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4231         CHECKGLERROR
4232         CHECKCGERROR
4233         if (r_cg_permutation != perm)
4234         {
4235                 r_cg_permutation = perm;
4236                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4237                 {
4238                         if (!r_cg_permutation->compiled)
4239                                 R_CG_CompilePermutation(perm, mode, permutation);
4240                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4241                         {
4242                                 // remove features until we find a valid permutation
4243                                 int i;
4244                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4245                                 {
4246                                         // reduce i more quickly whenever it would not remove any bits
4247                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4248                                         if (!(permutation & j))
4249                                                 continue;
4250                                         permutation -= j;
4251                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4252                                         if (!r_cg_permutation->compiled)
4253                                                 R_CG_CompilePermutation(perm, mode, permutation);
4254                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4255                                                 break;
4256                                 }
4257                                 if (i >= SHADERPERMUTATION_COUNT)
4258                                 {
4259                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4260                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4261                                         return; // no bit left to clear, entire mode is broken
4262                                 }
4263                         }
4264                 }
4265                 CHECKGLERROR
4266                 CHECKCGERROR
4267                 if (r_cg_permutation->vprogram)
4268                 {
4269                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4270                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4271                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4272                 }
4273                 else
4274                 {
4275                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4276                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4277                 }
4278                 if (r_cg_permutation->fprogram)
4279                 {
4280                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4281                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4282                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4283                 }
4284                 else
4285                 {
4286                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4287                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4288                 }
4289         }
4290         CHECKCGERROR
4291         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4292         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4293         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4294 }
4295
4296 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4297 {
4298         cgGLSetTextureParameter(param, R_GetTexture(tex));
4299         cgGLEnableTextureParameter(param);
4300 }
4301 #endif
4302
4303 #ifdef SUPPORTD3D
4304
4305 #ifdef SUPPORTD3D
4306 #include <d3d9.h>
4307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4308 extern D3DCAPS9 vid_d3d9caps;
4309 #endif
4310
4311 struct r_hlsl_permutation_s;
4312 typedef struct r_hlsl_permutation_s
4313 {
4314         /// hash lookup data
4315         struct r_hlsl_permutation_s *hashnext;
4316         unsigned int mode;
4317         unsigned int permutation;
4318
4319         /// indicates if we have tried compiling this permutation already
4320         qboolean compiled;
4321         /// NULL if compilation failed
4322         IDirect3DVertexShader9 *vertexshader;
4323         IDirect3DPixelShader9 *pixelshader;
4324 }
4325 r_hlsl_permutation_t;
4326
4327 typedef enum D3DVSREGISTER_e
4328 {
4329         D3DVSREGISTER_TexMatrix = 0, // float4x4
4330         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4331         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4332         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4333         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4334         D3DVSREGISTER_ModelToLight = 20, // float4x4
4335         D3DVSREGISTER_EyePosition = 24,
4336         D3DVSREGISTER_FogPlane = 25,
4337         D3DVSREGISTER_LightDir = 26,
4338         D3DVSREGISTER_LightPosition = 27,
4339 }
4340 D3DVSREGISTER_t;
4341
4342 typedef enum D3DPSREGISTER_e
4343 {
4344         D3DPSREGISTER_Alpha = 0,
4345         D3DPSREGISTER_BloomBlur_Parameters = 1,
4346         D3DPSREGISTER_ClientTime = 2,
4347         D3DPSREGISTER_Color_Ambient = 3,
4348         D3DPSREGISTER_Color_Diffuse = 4,
4349         D3DPSREGISTER_Color_Specular = 5,
4350         D3DPSREGISTER_Color_Glow = 6,
4351         D3DPSREGISTER_Color_Pants = 7,
4352         D3DPSREGISTER_Color_Shirt = 8,
4353         D3DPSREGISTER_DeferredColor_Ambient = 9,
4354         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4355         D3DPSREGISTER_DeferredColor_Specular = 11,
4356         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4357         D3DPSREGISTER_DeferredMod_Specular = 13,
4358         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4359         D3DPSREGISTER_EyePosition = 15, // unused
4360         D3DPSREGISTER_FogColor = 16,
4361         D3DPSREGISTER_FogHeightFade = 17,
4362         D3DPSREGISTER_FogPlane = 18,
4363         D3DPSREGISTER_FogPlaneViewDist = 19,
4364         D3DPSREGISTER_FogRangeRecip = 20,
4365         D3DPSREGISTER_LightColor = 21,
4366         D3DPSREGISTER_LightDir = 22, // unused
4367         D3DPSREGISTER_LightPosition = 23,
4368         D3DPSREGISTER_OffsetMapping_Scale = 24,
4369         D3DPSREGISTER_PixelSize = 25,
4370         D3DPSREGISTER_ReflectColor = 26,
4371         D3DPSREGISTER_ReflectFactor = 27,
4372         D3DPSREGISTER_ReflectOffset = 28,
4373         D3DPSREGISTER_RefractColor = 29,
4374         D3DPSREGISTER_Saturation = 30,
4375         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4376         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4377         D3DPSREGISTER_ScreenToDepth = 33,
4378         D3DPSREGISTER_ShadowMap_Parameters = 34,
4379         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4380         D3DPSREGISTER_SpecularPower = 36,
4381         D3DPSREGISTER_UserVec1 = 37,
4382         D3DPSREGISTER_UserVec2 = 38,
4383         D3DPSREGISTER_UserVec3 = 39,
4384         D3DPSREGISTER_UserVec4 = 40,
4385         D3DPSREGISTER_ViewTintColor = 41,
4386         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4387         D3DPSREGISTER_BloomColorSubtract = 43,
4388         D3DPSREGISTER_ViewToLight = 44, // float4x4
4389         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4390         // next at 52
4391 }
4392 D3DPSREGISTER_t;
4393
4394 /// information about each possible shader permutation
4395 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4396 /// currently selected permutation
4397 r_hlsl_permutation_t *r_hlsl_permutation;
4398 /// storage for permutations linked in the hash table
4399 memexpandablearray_t r_hlsl_permutationarray;
4400
4401 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4402 {
4403         //unsigned int hashdepth = 0;
4404         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4405         r_hlsl_permutation_t *p;
4406         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4407         {
4408                 if (p->mode == mode && p->permutation == permutation)
4409                 {
4410                         //if (hashdepth > 10)
4411                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4412                         return p;
4413                 }
4414                 //hashdepth++;
4415         }
4416         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4417         p->mode = mode;
4418         p->permutation = permutation;
4419         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4420         r_hlsl_permutationhash[mode][hashindex] = p;
4421         //if (hashdepth > 10)
4422         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4423         return p;
4424 }
4425
4426 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4427 {
4428         char *shaderstring;
4429         if (!filename || !filename[0])
4430                 return NULL;
4431         if (!strcmp(filename, "hlsl/default.hlsl"))
4432         {
4433                 if (!hlslshaderstring)
4434                 {
4435                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4436                         if (hlslshaderstring)
4437                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4438                         else
4439                                 hlslshaderstring = (char *)builtincgshaderstring;
4440                 }
4441                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4442                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4443                 return shaderstring;
4444         }
4445         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4446         if (shaderstring)
4447         {
4448                 if (printfromdisknotice)
4449                         Con_DPrintf("from disk %s... ", filename);
4450                 return shaderstring;
4451         }
4452         return shaderstring;
4453 }
4454
4455 #include <d3dx9.h>
4456 //#include <d3dx9shader.h>
4457 //#include <d3dx9mesh.h>
4458
4459 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4460 {
4461         DWORD *vsbin = NULL;
4462         DWORD *psbin = NULL;
4463         fs_offset_t vsbinsize;
4464         fs_offset_t psbinsize;
4465 //      IDirect3DVertexShader9 *vs = NULL;
4466 //      IDirect3DPixelShader9 *ps = NULL;
4467         ID3DXBuffer *vslog = NULL;
4468         ID3DXBuffer *vsbuffer = NULL;
4469         ID3DXConstantTable *vsconstanttable = NULL;
4470         ID3DXBuffer *pslog = NULL;
4471         ID3DXBuffer *psbuffer = NULL;
4472         ID3DXConstantTable *psconstanttable = NULL;
4473         int vsresult = 0;
4474         int psresult = 0;
4475         char temp[MAX_INPUTLINE];
4476         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4477         qboolean debugshader = gl_paranoid.integer != 0;
4478         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4479         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4480         if (!debugshader)
4481         {
4482                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4483                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4484         }
4485         if (debugshader || (!vsbin && vertstring) || (!psbin && fragstring))
4486         {
4487                 const char* dllnames_d3dx9 [] =
4488                 {
4489                         "d3dx9_43.dll",
4490                         "d3dx9_42.dll",
4491                         "d3dx9_41.dll",
4492                         "d3dx9_40.dll",
4493                         "d3dx9_39.dll",
4494                         "d3dx9_38.dll",
4495                         "d3dx9_37.dll",
4496                         "d3dx9_36.dll",
4497                         "d3dx9_35.dll",
4498                         "d3dx9_34.dll",
4499                         "d3dx9_33.dll",
4500                         "d3dx9_32.dll",
4501                         "d3dx9_31.dll",
4502                         "d3dx9_30.dll",
4503                         "d3dx9_29.dll",
4504                         "d3dx9_28.dll",
4505                         "d3dx9_27.dll",
4506                         "d3dx9_26.dll",
4507                         "d3dx9_25.dll",
4508                         "d3dx9_24.dll",
4509                         NULL
4510                 };
4511                 dllhandle_t d3dx9_dll = NULL;
4512                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4513                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4514                 dllfunction_t d3dx9_dllfuncs[] =
4515                 {
4516                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4517                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4518                         {NULL, NULL}
4519                 };
4520                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4521                 {
4522                         DWORD shaderflags = 0;
4523                         if (debugshader)
4524                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4525                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4526                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4527                         if (vertstring && vertstring[0])
4528                         {
4529                                 if (debugshader)
4530                                 {
4531                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4532                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4533                                 }
4534                                 else
4535                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4536                                 if (vsbuffer)
4537                                 {
4538                                         vsbinsize = vsbuffer->GetBufferSize();
4539                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4540                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4541                                         vsbuffer->Release();
4542                                 }
4543                                 if (vslog)
4544                                 {
4545                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4546                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4547                                         vslog->Release();
4548                                 }
4549                         }
4550                         if (fragstring && fragstring[0])
4551                         {
4552                                 if (debugshader)
4553                                 {
4554                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4555                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4556                                 }
4557                                 else
4558                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4559                                 if (psbuffer)
4560                                 {
4561                                         psbinsize = psbuffer->GetBufferSize();
4562                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4563                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4564                                         psbuffer->Release();
4565                                 }
4566                                 if (pslog)
4567                                 {
4568                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4569                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4570                                         pslog->Release();
4571                                 }
4572                         }
4573                         Sys_UnloadLibrary(&d3dx9_dll);
4574                 }
4575                 else
4576                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4577         }
4578         if (vsbin)
4579         {
4580                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4581                 if (FAILED(vsresult))
4582                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4583         }
4584         if (psbin)
4585         {
4586                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4587                 if (FAILED(psresult))
4588                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4589         }
4590         // free the shader data
4591         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4592         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4593 }
4594
4595 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4596 {
4597         int i;
4598         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4599         int vertstrings_count = 0, vertstring_length = 0;
4600         int geomstrings_count = 0, geomstring_length = 0;
4601         int fragstrings_count = 0, fragstring_length = 0;
4602         char *t;
4603         char *vertexstring, *geometrystring, *fragmentstring;
4604         char *vertstring, *geomstring, *fragstring;
4605         const char *vertstrings_list[32+3];
4606         const char *geomstrings_list[32+3];
4607         const char *fragstrings_list[32+3];
4608         char permutationname[256];
4609         char cachename[256];
4610
4611         if (p->compiled)
4612                 return;
4613         p->compiled = true;
4614         p->vertexshader = NULL;
4615         p->pixelshader = NULL;
4616
4617         permutationname[0] = 0;
4618         cachename[0] = 0;
4619         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4620         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4621         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4622
4623         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4624         strlcat(cachename, "hlsl/", sizeof(cachename));
4625
4626         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4627         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4628         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4629         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4630
4631         // the first pretext is which type of shader to compile as
4632         // (later these will all be bound together as a program object)
4633         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4634         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4635         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4636
4637         // the second pretext is the mode (for example a light source)
4638         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4639         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4640         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4641         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4642         strlcat(cachename, modeinfo->name, sizeof(cachename));
4643
4644         // now add all the permutation pretexts
4645         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4646         {
4647                 if (permutation & (1<<i))
4648                 {
4649                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4650                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4651                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4652                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4653                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4654                 }
4655                 else
4656                 {
4657                         // keep line numbers correct
4658                         vertstrings_list[vertstrings_count++] = "\n";
4659                         geomstrings_list[geomstrings_count++] = "\n";
4660                         fragstrings_list[fragstrings_count++] = "\n";
4661                 }
4662         }
4663
4664         // replace spaces in the cachename with _ characters
4665         for (i = 0;cachename[i];i++)
4666                 if (cachename[i] == ' ')
4667                         cachename[i] = '_';
4668
4669         // now append the shader text itself
4670         vertstrings_list[vertstrings_count++] = vertexstring;
4671         geomstrings_list[geomstrings_count++] = geometrystring;
4672         fragstrings_list[fragstrings_count++] = fragmentstring;
4673
4674         // if any sources were NULL, clear the respective list
4675         if (!vertexstring)
4676                 vertstrings_count = 0;
4677         if (!geometrystring)
4678                 geomstrings_count = 0;
4679         if (!fragmentstring)
4680                 fragstrings_count = 0;
4681
4682         vertstring_length = 0;
4683         for (i = 0;i < vertstrings_count;i++)
4684                 vertstring_length += strlen(vertstrings_list[i]);
4685         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4686         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4687                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4688
4689         geomstring_length = 0;
4690         for (i = 0;i < geomstrings_count;i++)
4691                 geomstring_length += strlen(geomstrings_list[i]);
4692         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4693         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4694                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4695
4696         fragstring_length = 0;
4697         for (i = 0;i < fragstrings_count;i++)
4698                 fragstring_length += strlen(fragstrings_list[i]);
4699         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4700         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4701                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4702
4703         // try to load the cached shader, or generate one
4704         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4705
4706         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4707                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4708         else
4709                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4710
4711         // free the strings
4712         if (vertstring)
4713                 Mem_Free(vertstring);
4714         if (geomstring)
4715                 Mem_Free(geomstring);
4716         if (fragstring)
4717                 Mem_Free(fragstring);
4718         if (vertexstring)
4719                 Mem_Free(vertexstring);
4720         if (geometrystring)
4721                 Mem_Free(geometrystring);
4722         if (fragmentstring)
4723                 Mem_Free(fragmentstring);
4724 }
4725
4726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4728 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);}
4729 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);}
4730 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);}
4731 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);}
4732
4733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4735 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);}
4736 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);}
4737 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);}
4738 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);}
4739
4740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4741 {
4742         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4743         if (r_hlsl_permutation != perm)
4744         {
4745                 r_hlsl_permutation = perm;
4746                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4747                 {
4748                         if (!r_hlsl_permutation->compiled)
4749                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4750                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4751                         {
4752                                 // remove features until we find a valid permutation
4753                                 int i;
4754                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4755                                 {
4756                                         // reduce i more quickly whenever it would not remove any bits
4757                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4758                                         if (!(permutation & j))
4759                                                 continue;
4760                                         permutation -= j;
4761                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4762                                         if (!r_hlsl_permutation->compiled)
4763                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4764                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4765                                                 break;
4766                                 }
4767                                 if (i >= SHADERPERMUTATION_COUNT)
4768                                 {
4769                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4771                                         return; // no bit left to clear, entire mode is broken
4772                                 }
4773                         }
4774                 }
4775                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4776                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4777         }
4778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4780         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4781 }
4782 #endif
4783
4784 void R_GLSL_Restart_f(void)
4785 {
4786         unsigned int i, limit;
4787         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4788                 Mem_Free(glslshaderstring);
4789         glslshaderstring = NULL;
4790         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4791                 Mem_Free(cgshaderstring);
4792         cgshaderstring = NULL;
4793         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4794                 Mem_Free(hlslshaderstring);
4795         hlslshaderstring = NULL;
4796         switch(vid.renderpath)
4797         {
4798         case RENDERPATH_D3D9:
4799 #ifdef SUPPORTD3D
4800                 {
4801                         r_hlsl_permutation_t *p;
4802                         r_hlsl_permutation = NULL;
4803 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4804 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4805 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4806 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4807                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4808                         for (i = 0;i < limit;i++)
4809                         {
4810                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4811                                 {
4812                                         if (p->vertexshader)
4813                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4814                                         if (p->pixelshader)
4815                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4816                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4817                                 }
4818                         }
4819                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4820                 }
4821 #endif
4822                 break;
4823         case RENDERPATH_D3D10:
4824                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4825                 break;
4826         case RENDERPATH_D3D11:
4827                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4828                 break;
4829         case RENDERPATH_GL20:
4830                 {
4831                         r_glsl_permutation_t *p;
4832                         r_glsl_permutation = NULL;
4833                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4834                         for (i = 0;i < limit;i++)
4835                         {
4836                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4837                                 {
4838                                         GL_Backend_FreeProgram(p->program);
4839                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4840                                 }
4841                         }
4842                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4843                 }
4844                 break;
4845         case RENDERPATH_CGGL:
4846 #ifdef SUPPORTCG
4847                 {
4848                         r_cg_permutation_t *p;
4849                         r_cg_permutation = NULL;
4850                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4851                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4852                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4853                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4854                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
4855                         for (i = 0;i < limit;i++)
4856                         {
4857                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
4858                                 {
4859                                         if (p->vprogram)
4860                                                 cgDestroyProgram(p->vprogram);
4861                                         if (p->fprogram)
4862                                                 cgDestroyProgram(p->fprogram);
4863                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
4864                                 }
4865                         }
4866                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
4867                 }
4868 #endif
4869                 break;
4870         case RENDERPATH_GL13:
4871         case RENDERPATH_GL11:
4872                 break;
4873         }
4874 }
4875
4876 void R_GLSL_DumpShader_f(void)
4877 {
4878         int i;
4879         qfile_t *file;
4880
4881         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4882         if (file)
4883         {
4884                 FS_Print(file, "/* The engine may define the following macros:\n");
4885                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4886                 for (i = 0;i < SHADERMODE_COUNT;i++)
4887                         FS_Print(file, glslshadermodeinfo[i].pretext);
4888                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4889                         FS_Print(file, shaderpermutationinfo[i].pretext);
4890                 FS_Print(file, "*/\n");
4891                 FS_Print(file, builtinshaderstring);
4892                 FS_Close(file);
4893                 Con_Printf("glsl/default.glsl written\n");
4894         }
4895         else
4896                 Con_Printf("failed to write to glsl/default.glsl\n");
4897
4898 #ifdef SUPPORTCG
4899         file = FS_OpenRealFile("cg/default.cg", "w", false);
4900         if (file)
4901         {
4902                 FS_Print(file, "/* The engine may define the following macros:\n");
4903                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4904                 for (i = 0;i < SHADERMODE_COUNT;i++)
4905                         FS_Print(file, cgshadermodeinfo[i].pretext);
4906                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4907                         FS_Print(file, shaderpermutationinfo[i].pretext);
4908                 FS_Print(file, "*/\n");
4909                 FS_Print(file, builtincgshaderstring);
4910                 FS_Close(file);
4911                 Con_Printf("cg/default.cg written\n");
4912         }
4913         else
4914                 Con_Printf("failed to write to cg/default.cg\n");
4915 #endif
4916
4917 #ifdef SUPPORTD3D
4918         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4919         if (file)
4920         {
4921                 FS_Print(file, "/* The engine may define the following macros:\n");
4922                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4923                 for (i = 0;i < SHADERMODE_COUNT;i++)
4924                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4925                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4926                         FS_Print(file, shaderpermutationinfo[i].pretext);
4927                 FS_Print(file, "*/\n");
4928                 FS_Print(file, builtincgshaderstring);
4929                 FS_Close(file);
4930                 Con_Printf("hlsl/default.hlsl written\n");
4931         }
4932         else
4933                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4934 #endif
4935 }
4936
4937 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4938 {
4939         if (!second)
4940                 texturemode = GL_MODULATE;
4941         switch (vid.renderpath)
4942         {
4943         case RENDERPATH_D3D9:
4944 #ifdef SUPPORTD3D
4945                 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))));
4946                 R_Mesh_TexBind(GL20TU_FIRST , first );
4947                 R_Mesh_TexBind(GL20TU_SECOND, second);
4948 #endif
4949                 break;
4950         case RENDERPATH_D3D10:
4951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4952                 break;
4953         case RENDERPATH_D3D11:
4954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4955                 break;
4956         case RENDERPATH_GL20:
4957                 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))));
4958                 R_Mesh_TexBind(GL20TU_FIRST , first );
4959                 R_Mesh_TexBind(GL20TU_SECOND, second);
4960                 break;
4961         case RENDERPATH_CGGL:
4962 #ifdef SUPPORTCG
4963                 CHECKCGERROR
4964                 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))));
4965                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
4966                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
4967 #endif
4968                 break;
4969         case RENDERPATH_GL13:
4970                 R_Mesh_TexBind(0, first );
4971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4972                 R_Mesh_TexBind(1, second);
4973                 if (second)
4974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4975                 break;
4976         case RENDERPATH_GL11:
4977                 R_Mesh_TexBind(0, first );
4978                 break;
4979         }
4980 }
4981
4982 void R_SetupShader_DepthOrShadow(void)
4983 {
4984         switch (vid.renderpath)
4985         {
4986         case RENDERPATH_D3D9:
4987 #ifdef SUPPORTD3D
4988                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4989 #endif
4990                 break;
4991         case RENDERPATH_D3D10:
4992                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4993                 break;
4994         case RENDERPATH_D3D11:
4995                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4996                 break;
4997         case RENDERPATH_GL20:
4998                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4999                 break;
5000         case RENDERPATH_CGGL:
5001 #ifdef SUPPORTCG
5002                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5003 #endif
5004                 break;
5005         case RENDERPATH_GL13:
5006                 R_Mesh_TexBind(0, 0);
5007                 R_Mesh_TexBind(1, 0);
5008                 break;
5009         case RENDERPATH_GL11:
5010                 R_Mesh_TexBind(0, 0);
5011                 break;
5012         }
5013 }
5014
5015 void R_SetupShader_ShowDepth(void)
5016 {
5017         switch (vid.renderpath)
5018         {
5019         case RENDERPATH_D3D9:
5020 #ifdef SUPPORTHLSL
5021                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5022 #endif
5023                 break;
5024         case RENDERPATH_D3D10:
5025                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5026                 break;
5027         case RENDERPATH_D3D11:
5028                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5029                 break;
5030         case RENDERPATH_GL20:
5031                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5032                 break;
5033         case RENDERPATH_CGGL:
5034 #ifdef SUPPORTCG
5035                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5036 #endif
5037                 break;
5038         case RENDERPATH_GL13:
5039                 break;
5040         case RENDERPATH_GL11:
5041                 break;
5042         }
5043 }
5044
5045 extern qboolean r_shadow_usingdeferredprepass;
5046 extern cvar_t r_shadow_deferred_8bitrange;
5047 extern rtexture_t *r_shadow_attenuationgradienttexture;
5048 extern rtexture_t *r_shadow_attenuation2dtexture;
5049 extern rtexture_t *r_shadow_attenuation3dtexture;
5050 extern qboolean r_shadow_usingshadowmap2d;
5051 extern qboolean r_shadow_usingshadowmaportho;
5052 extern float r_shadow_shadowmap_texturescale[2];
5053 extern float r_shadow_shadowmap_parameters[4];
5054 extern qboolean r_shadow_shadowmapvsdct;
5055 extern qboolean r_shadow_shadowmapsampler;
5056 extern int r_shadow_shadowmappcf;
5057 extern rtexture_t *r_shadow_shadowmap2dtexture;
5058 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5059 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5060 extern matrix4x4_t r_shadow_shadowmapmatrix;
5061 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5062 extern int r_shadow_prepass_width;
5063 extern int r_shadow_prepass_height;
5064 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5065 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5066 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5067 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5068 extern cvar_t gl_mesh_separatearrays;
5069 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5070 {
5071         // a blendfunc allows colormod if:
5072         // a) it can never keep the destination pixel invariant, or
5073         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5074         // this is to prevent unintended side effects from colormod
5075
5076         // in formulas:
5077         // IF there is a (s, sa) for which for all (d, da),
5078         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5079         // THEN, for this (s, sa) and all (colormod, d, da):
5080         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5081         // OBVIOUSLY, this means that
5082         //   s*colormod * src(s*colormod, d, sa, da) = 0
5083         //   dst(s*colormod, d, sa, da)              = 1
5084
5085         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5086
5087         // main condition to leave dst color invariant:
5088         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5089         //   src == GL_ZERO:
5090         //     s * 0 + d * dst(s, d, sa, da) == d
5091         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5092         //       => colormod is a problem for GL_SRC_COLOR only
5093         //   src == GL_ONE:
5094         //     s + d * dst(s, d, sa, da) == d
5095         //       => s == 0
5096         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5097         //       => colormod is never problematic for these
5098         //   src == GL_SRC_COLOR:
5099         //     s*s + d * dst(s, d, sa, da) == d
5100         //       => s == 0
5101         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5102         //       => colormod is never problematic for these
5103         //   src == GL_ONE_MINUS_SRC_COLOR:
5104         //     s*(1-s) + d * dst(s, d, sa, da) == d
5105         //       => s == 0 or s == 1
5106         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5107         //       => colormod is a problem for GL_SRC_COLOR only
5108         //   src == GL_DST_COLOR
5109         //     s*d + d * dst(s, d, sa, da) == d
5110         //       => s == 1
5111         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5112         //       => colormod is always a problem
5113         //     or
5114         //       => s == 0
5115         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5116         //       => colormod is never problematic for these
5117         //       => BUT, we do not know s! We must assume it is problematic
5118         //       then... except in GL_ONE case, where we know all invariant
5119         //       cases are fine
5120         //   src == GL_ONE_MINUS_DST_COLOR
5121         //     s*(1-d) + d * dst(s, d, sa, da) == d
5122         //       => s == 0 (1-d is impossible to handle for our desired result)
5123         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5124         //       => colormod is never problematic for these
5125         //   src == GL_SRC_ALPHA
5126         //     s*sa + d * dst(s, d, sa, da) == d
5127         //       => s == 0, or sa == 0
5128         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5129         //       => colormod breaks in the case GL_SRC_COLOR only
5130         //   src == GL_ONE_MINUS_SRC_ALPHA
5131         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5132         //       => s == 0, or sa == 1
5133         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5134         //       => colormod breaks in the case GL_SRC_COLOR only
5135         //   src == GL_DST_ALPHA
5136         //     s*da + d * dst(s, d, sa, da) == d
5137         //       => s == 0
5138         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5139         //       => colormod is never problematic for these
5140
5141         switch(src)
5142         {
5143                 case GL_ZERO:
5144                 case GL_ONE_MINUS_SRC_COLOR:
5145                 case GL_SRC_ALPHA:
5146                 case GL_ONE_MINUS_SRC_ALPHA:
5147                         if(dst == GL_SRC_COLOR)
5148                                 return false;
5149                         return true;
5150                 case GL_ONE:
5151                 case GL_SRC_COLOR:
5152                 case GL_ONE_MINUS_DST_COLOR:
5153                 case GL_DST_ALPHA:
5154                 case GL_ONE_MINUS_DST_ALPHA:
5155                         return true;
5156                 case GL_DST_COLOR:
5157                         if(dst == GL_ONE)
5158                                 return true;
5159                         return false;
5160                 default:
5161                         return false;
5162         }
5163 }
5164 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)
5165 {
5166         // select a permutation of the lighting shader appropriate to this
5167         // combination of texture, entity, light source, and fogging, only use the
5168         // minimum features necessary to avoid wasting rendering time in the
5169         // fragment shader on features that are not being used
5170         unsigned int permutation = 0;
5171         unsigned int mode = 0;
5172         qboolean allow_colormod;
5173         static float dummy_colormod[3] = {1, 1, 1};
5174         float *colormod = rsurface.colormod;
5175         float m16f[16];
5176         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5177         if (rsurfacepass == RSURFPASS_BACKGROUND)
5178         {
5179                 // distorted background
5180                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5181                         mode = SHADERMODE_WATER;
5182                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5183                         mode = SHADERMODE_REFRACTION;
5184                 else
5185                 {
5186                         mode = SHADERMODE_GENERIC;
5187                         permutation |= SHADERPERMUTATION_DIFFUSE;
5188                 }
5189                 GL_AlphaTest(false);
5190                 GL_BlendFunc(GL_ONE, GL_ZERO);
5191                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5192         }
5193         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5194         {
5195                 if (r_glsl_offsetmapping.integer)
5196                 {
5197                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5198                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5199                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5200                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5201                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5202                         {
5203                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5204                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5205                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5206                         }
5207                 }
5208                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5209                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5210                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5211                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5212                 // normalmap (deferred prepass), may use alpha test on diffuse
5213                 mode = SHADERMODE_DEFERREDGEOMETRY;
5214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5215                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5216                 GL_AlphaTest(false);
5217                 GL_BlendFunc(GL_ONE, GL_ZERO);
5218                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5219         }
5220         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5221         {
5222                 if (r_glsl_offsetmapping.integer)
5223                 {
5224                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5225                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5226                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5227                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5228                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5229                         {
5230                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5231                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5232                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5233                         }
5234                 }
5235                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5236                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5237                 // light source
5238                 mode = SHADERMODE_LIGHTSOURCE;
5239                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5240                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5241                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5242                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5243                 if (diffusescale > 0)
5244                         permutation |= SHADERPERMUTATION_DIFFUSE;
5245                 if (specularscale > 0)
5246                 {
5247                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5248                         if (r_shadow_glossexact.integer)
5249                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5250                 }
5251                 if (r_refdef.fogenabled)
5252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5253                 if (rsurface.texture->colormapping)
5254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5255                 if (r_shadow_usingshadowmap2d)
5256                 {
5257                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5258                         if(r_shadow_shadowmapvsdct)
5259                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5260
5261                         if (r_shadow_shadowmapsampler)
5262                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5263                         if (r_shadow_shadowmappcf > 1)
5264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5265                         else if (r_shadow_shadowmappcf)
5266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5267                 }
5268                 if (rsurface.texture->reflectmasktexture)
5269                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5270                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5271                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5272                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5273         }
5274         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5275         {
5276                 if (r_glsl_offsetmapping.integer)
5277                 {
5278                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5279                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5280                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5281                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5282                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5283                         {
5284                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5285                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5286                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5287                         }
5288                 }
5289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5291                 // unshaded geometry (fullbright or ambient model lighting)
5292                 mode = SHADERMODE_FLATCOLOR;
5293                 ambientscale = diffusescale = specularscale = 0;
5294                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5295                         permutation |= SHADERPERMUTATION_GLOW;
5296                 if (r_refdef.fogenabled)
5297                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5298                 if (rsurface.texture->colormapping)
5299                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5300                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5301                 {
5302                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5303                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5304
5305                         if (r_shadow_shadowmapsampler)
5306                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5307                         if (r_shadow_shadowmappcf > 1)
5308                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5309                         else if (r_shadow_shadowmappcf)
5310                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5311                 }
5312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5313                         permutation |= SHADERPERMUTATION_REFLECTION;
5314                 if (rsurface.texture->reflectmasktexture)
5315                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5316                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5317                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5318                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5319         }
5320         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5321         {
5322                 if (r_glsl_offsetmapping.integer)
5323                 {
5324                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5325                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5326                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5327                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5328                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5329                         {
5330                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5331                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5332                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5333                         }
5334                 }
5335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5336                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5337                 // directional model lighting
5338                 mode = SHADERMODE_LIGHTDIRECTION;
5339                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5340                         permutation |= SHADERPERMUTATION_GLOW;
5341                 permutation |= SHADERPERMUTATION_DIFFUSE;
5342                 if (specularscale > 0)
5343                 {
5344                         permutation |= SHADERPERMUTATION_SPECULAR;
5345                         if (r_shadow_glossexact.integer)
5346                                 permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5347                 }
5348                 if (r_refdef.fogenabled)
5349                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5350                 if (rsurface.texture->colormapping)
5351                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5352                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5353                 {
5354                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5355                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5356
5357                         if (r_shadow_shadowmapsampler)
5358                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5359                         if (r_shadow_shadowmappcf > 1)
5360                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5361                         else if (r_shadow_shadowmappcf)
5362                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5363                 }
5364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5365                         permutation |= SHADERPERMUTATION_REFLECTION;
5366                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5367                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5368                 if (rsurface.texture->reflectmasktexture)
5369                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5370                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5371                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5372                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5373         }
5374         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5375         {
5376                 if (r_glsl_offsetmapping.integer)
5377                 {
5378                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5379                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5380                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5381                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5382                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5383                         {
5384                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5385                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5386                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5387                         }
5388                 }
5389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5390                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5391                 // ambient model lighting
5392                 mode = SHADERMODE_LIGHTDIRECTION;
5393                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5394                         permutation |= SHADERPERMUTATION_GLOW;
5395                 if (r_refdef.fogenabled)
5396                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5397                 if (rsurface.texture->colormapping)
5398                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5399                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5400                 {
5401                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5402                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5403
5404                         if (r_shadow_shadowmapsampler)
5405                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5406                         if (r_shadow_shadowmappcf > 1)
5407                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5408                         else if (r_shadow_shadowmappcf)
5409                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5410                 }
5411                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5412                         permutation |= SHADERPERMUTATION_REFLECTION;
5413                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5414                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5415                 if (rsurface.texture->reflectmasktexture)
5416                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5417                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5418                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5419                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5420         }
5421         else
5422         {
5423                 if (r_glsl_offsetmapping.integer)
5424                 {
5425                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5426                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5427                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5428                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5429                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5430                         {
5431                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5432                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5433                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5434                         }
5435                 }
5436                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5437                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5438                 // lightmapped wall
5439                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5440                         permutation |= SHADERPERMUTATION_GLOW;
5441                 if (r_refdef.fogenabled)
5442                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443                 if (rsurface.texture->colormapping)
5444                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5445                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5446                 {
5447                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5448                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5449
5450                         if (r_shadow_shadowmapsampler)
5451                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5452                         if (r_shadow_shadowmappcf > 1)
5453                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5454                         else if (r_shadow_shadowmappcf)
5455                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5456                 }
5457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5458                         permutation |= SHADERPERMUTATION_REFLECTION;
5459                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5460                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5461                 if (rsurface.texture->reflectmasktexture)
5462                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5463                 if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5464                 {
5465                         // deluxemapping (light direction texture)
5466                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5468                         else
5469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5470                         permutation |= SHADERPERMUTATION_DIFFUSE;
5471                         if (specularscale > 0)
5472                         {
5473                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5474                                 if (r_shadow_glossexact.integer)
5475                                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
5476                         }
5477                 }
5478                 else if (r_glsl_deluxemapping.integer >= 2)
5479                 {
5480                         // fake deluxemapping (uniform light direction in tangentspace)
5481                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
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                 }
5490                 else if (rsurface.uselightmaptexture)
5491                 {
5492                         // ordinary lightmapping (q1bsp, q3bsp)
5493                         mode = SHADERMODE_LIGHTMAP;
5494                 }
5495                 else
5496                 {
5497                         // ordinary vertex coloring (q3bsp)
5498                         mode = SHADERMODE_VERTEXCOLOR;
5499                 }
5500                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5501                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5502                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5503         }
5504         if(!allow_colormod)
5505                 colormod = dummy_colormod;
5506         switch(vid.renderpath)
5507         {
5508         case RENDERPATH_D3D9:
5509 #ifdef SUPPORTD3D
5510                 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);
5511                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5512                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5513                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5514                 if (mode == SHADERMODE_LIGHTSOURCE)
5515                 {
5516                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5517                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5518                 }
5519                 else
5520                 {
5521                         if (mode == SHADERMODE_LIGHTDIRECTION)                                   
5522                         {
5523                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5524                         }
5525                 }
5526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5527                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5528                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5529                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5530                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5531
5532                 if (mode == SHADERMODE_LIGHTSOURCE)
5533                 {
5534                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5535                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5538                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5539
5540                         // additive passes are only darkened by fog, not tinted
5541                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5542                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5543                 }
5544                 else
5545                 {
5546                         if (mode == SHADERMODE_FLATCOLOR)
5547                         {
5548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5549                         }
5550                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5551                         {
5552                                 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]);
5553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5554                                 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);
5555                                 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);
5556                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5558                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5559                         }
5560                         else
5561                         {
5562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5564                                 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);
5565                                 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);
5566                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5567                         }
5568                         // additive passes are only darkened by fog, not tinted
5569                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5571                         else
5572                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5573                         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);
5574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5575                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5576                         hlslPSSetParameter4fv(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f);
5577                         hlslPSSetParameter4fv(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f);
5578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5579                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5580                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5581                 }
5582                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5583                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5584                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5585                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3]);
5586                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5587                 if (rsurface.texture->pantstexture)
5588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5589                 else
5590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5591                 if (rsurface.texture->shirttexture)
5592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5593                 else
5594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5595                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5596                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5597                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5598                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5599                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5600                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5601                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5602
5603                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5604                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5605                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5606                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5607                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5608                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5609                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5610                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5611                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5612                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5613                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5614                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5615                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5616                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5617                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5618                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5619                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5620                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5621                 {
5622                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5623                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5624                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5625                 }
5626                 else
5627                 {
5628                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5629                 }
5630 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5631 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5632                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5633                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5634                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5635                 {
5636                         R_Mesh_TexBind((permutation & SHADERPERMUTATION_SHADOWMAPORTHO) ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, (permutation & SHADERPERMUTATION_SHADOWSAMPLER) ? r_shadow_shadowmap2dtexture : r_shadow_shadowmap2dcolortexture);
5637                         if (rsurface.rtlight)
5638                         {
5639                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5640                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5641                         }
5642                 }
5643 #endif
5644                 break;
5645         case RENDERPATH_D3D10:
5646                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5647                 break;
5648         case RENDERPATH_D3D11:
5649                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5650                 break;
5651         case RENDERPATH_GL20:
5652                 if (gl_mesh_separatearrays.integer)
5653                 {
5654                         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);
5655                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5656                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5657                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5658                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5659                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5660                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5661                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5662                 }
5663                 else
5664                 {
5665                         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);
5666                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5667                 }
5668                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5669                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5670                 if (mode == SHADERMODE_LIGHTSOURCE)
5671                 {
5672                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5673                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5674                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5675                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5676                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5677                         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);
5678         
5679                         // additive passes are only darkened by fog, not tinted
5680                         if (r_glsl_permutation->loc_FogColor >= 0)
5681                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5682                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5683                 }
5684                 else
5685                 {
5686                         if (mode == SHADERMODE_FLATCOLOR)
5687                         {
5688                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5689                         }
5690                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5691                         {
5692                                 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]);
5693                                 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]);
5694                                 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);
5695                                 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);
5696                                 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);
5697                                 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]);
5698                                 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]);
5699                         }
5700                         else
5701                         {
5702                                 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]);
5703                                 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]);
5704                                 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);
5705                                 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);
5706                                 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);
5707                         }
5708                         // additive passes are only darkened by fog, not tinted
5709                         if (r_glsl_permutation->loc_FogColor >= 0)
5710                         {
5711                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5712                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5713                                 else
5714                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5715                         }
5716                         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);
5717                         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]);
5718                         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]);
5719                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_RefractColor, 1, rsurface.texture->refractcolor4f);
5720                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fvARB(r_glsl_permutation->loc_ReflectColor, 1, rsurface.texture->reflectcolor4f);
5721                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5722                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5723                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
5724                 }
5725                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5726                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5727                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5728                 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]);
5729                 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]);
5730
5731                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5732                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3]);
5733                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5734                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5735                 {
5736                         if (rsurface.texture->pantstexture)
5737                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5738                         else
5739                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5740                 }
5741                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5742                 {
5743                         if (rsurface.texture->shirttexture)
5744                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5745                         else
5746                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5747                 }
5748                 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]);
5749                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5750                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5751                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5752                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5753                 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]);
5754                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5755
5756         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5757         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5758         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5759                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5760                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5761                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5762                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5763                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5764                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5765                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5766                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5767                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5768                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5769                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5770                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5771                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5772                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5773                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5774                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5775                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5776                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5777                 {
5778                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5779                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5780                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5781                 }
5782                 else
5783                 {
5784                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5785                 }
5786 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5787 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5788                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5789                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5790                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5791                 {
5792                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_shadow_usingshadowmaportho ? GL20TU_SHADOWMAPORTHO2D : GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5793                         if (rsurface.rtlight)
5794                         {
5795                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5796                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5797                         }
5798                 }
5799                 CHECKGLERROR
5800                 break;
5801         case RENDERPATH_CGGL:
5802 #ifdef SUPPORTCG
5803                 if (gl_mesh_separatearrays.integer)
5804                 {
5805                         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);
5806                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5807                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5808                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5809                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5810                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5811                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5812                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5813                 }
5814                 else
5815                 {
5816                         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);
5817                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5818                 }
5819                 R_SetupShader_SetPermutationCG(mode, permutation);
5820                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
5821                 if (mode == SHADERMODE_LIGHTSOURCE)
5822                 {
5823                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
5824                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5825                 }
5826                 else
5827                 {
5828                         if (mode == SHADERMODE_LIGHTDIRECTION)
5829                         {
5830                                 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
5831                         }
5832                 }
5833                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
5834                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
5835                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
5836                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5837                 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
5838                 CHECKGLERROR
5839
5840                 if (mode == SHADERMODE_LIGHTSOURCE)
5841                 {
5842                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
5843                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
5844                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
5845                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
5846                         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
5847
5848                         // additive passes are only darkened by fog, not tinted
5849                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
5850                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5851                 }
5852                 else
5853                 {
5854                         if (mode == SHADERMODE_FLATCOLOR)
5855                         {
5856                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
5857                         }
5858                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5859                         {
5860                                 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
5861                                 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
5862                                 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
5863                                 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
5864                                 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
5865                                 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
5866                                 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
5867                         }
5868                         else
5869                         {
5870                                 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
5871                                 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
5872                                 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
5873                                 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
5874                                 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
5875                         }
5876                         // additive passes are only darkened by fog, not tinted
5877                         if (r_cg_permutation->fp_FogColor)
5878                         {
5879                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5880                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
5881                                 else
5882                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5883                                 CHECKCGERROR
5884                         }
5885                         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
5886                         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
5887                         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
5888                         if (r_cg_permutation->fp_RefractColor) cgGLSetParameter4fv(r_cg_permutation->fp_RefractColor, rsurface.texture->refractcolor4f);CHECKCGERROR
5889                         if (r_cg_permutation->fp_ReflectColor) cgGLSetParameter4fv(r_cg_permutation->fp_ReflectColor, rsurface.texture->reflectcolor4f);CHECKCGERROR
5890                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
5891                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
5892                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));CHECKCGERROR
5893                 }
5894                 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
5895                 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
5896                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
5897                 if (r_cg_permutation->fp_Alpha) cgGLSetParameter1f(r_cg_permutation->fp_Alpha, rsurface.texture->lightmapcolor[3]);CHECKCGERROR
5898                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
5899                 if (r_cg_permutation->fp_Color_Pants)
5900                 {
5901                         if (rsurface.texture->pantstexture)
5902                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5903                         else
5904                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
5905                         CHECKCGERROR
5906                 }
5907                 if (r_cg_permutation->fp_Color_Shirt)
5908                 {
5909                         if (rsurface.texture->shirttexture)
5910                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5911                         else
5912                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
5913                         CHECKCGERROR
5914                 }
5915                 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
5916                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
5917                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
5918                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
5919                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
5920                 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
5921                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
5922
5923         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
5924         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
5925         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
5926                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
5927                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
5928                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
5929                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
5930                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
5931                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
5932                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
5933                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
5934                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
5935                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
5936                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
5937                 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
5938                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
5939                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
5940                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
5941                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
5942                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
5943                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5944                 {
5945                         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
5946                         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
5947                         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
5948                 }
5949                 else
5950                 {
5951                         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
5952                 }
5953                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
5954                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
5955                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
5956                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
5957                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5958                 {
5959                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
5960                         if (rsurface.rtlight)
5961                         {
5962                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
5963                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
5964                         }
5965                 }
5966
5967                 CHECKGLERROR
5968 #endif
5969                 break;
5970         case RENDERPATH_GL13:
5971         case RENDERPATH_GL11:
5972                 break;
5973         }
5974 }
5975
5976 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5977 {
5978         // select a permutation of the lighting shader appropriate to this
5979         // combination of texture, entity, light source, and fogging, only use the
5980         // minimum features necessary to avoid wasting rendering time in the
5981         // fragment shader on features that are not being used
5982         unsigned int permutation = 0;
5983         unsigned int mode = 0;
5984         const float *lightcolorbase = rtlight->currentcolor;
5985         float ambientscale = rtlight->ambientscale;
5986         float diffusescale = rtlight->diffusescale;
5987         float specularscale = rtlight->specularscale;
5988         // this is the location of the light in view space
5989         vec3_t viewlightorigin;
5990         // this transforms from view space (camera) to light space (cubemap)
5991         matrix4x4_t viewtolight;
5992         matrix4x4_t lighttoview;
5993         float viewtolight16f[16];
5994         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5995         // light source
5996         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5997         if (rtlight->currentcubemap != r_texture_whitecube)
5998                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5999         if (diffusescale > 0)
6000                 permutation |= SHADERPERMUTATION_DIFFUSE;
6001         if (specularscale > 0)
6002         {
6003                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6004                 if (r_shadow_glossexact.integer)
6005                         permutation |= SHADERPERMUTATION_EXACTSPECULARMATH;
6006         }
6007         if (r_shadow_usingshadowmap2d)
6008         {
6009                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6010                 if (r_shadow_shadowmapvsdct)
6011                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6012
6013                 if (r_shadow_shadowmapsampler)
6014                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6015                 if (r_shadow_shadowmappcf > 1)
6016                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6017                 else if (r_shadow_shadowmappcf)
6018                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6019         }
6020         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6021         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6022         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6023         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6024         switch(vid.renderpath)
6025         {
6026         case RENDERPATH_D3D9:
6027 #ifdef SUPPORTD3D
6028                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6029                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6030                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6031                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6032                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6033                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6034                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6035                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6036                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * ((permutation & SHADERPERMUTATION_EXACTSPECULARMATH) ? 0.25f : 1.0f));
6037                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6038                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6039
6040                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6041                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6042                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6043                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6044                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6045                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6046 #endif
6047                 break;
6048         case RENDERPATH_D3D10:
6049                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6050                 break;
6051         case RENDERPATH_D3D11:
6052                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6053                 break;
6054         case RENDERPATH_GL20:
6055                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6056                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6057                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6058                 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);
6059                 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);
6060                 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);
6061                 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]);
6062                 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]);
6063                 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));
6064                 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]);
6065                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6066
6067                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6068                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6069                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6070                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6071                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6072                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6073                 break;
6074         case RENDERPATH_CGGL:
6075 #ifdef SUPPORTCG
6076                 R_SetupShader_SetPermutationCG(mode, permutation);
6077                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6078                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6079                 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
6080                 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
6081                 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
6082                 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
6083                 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
6084                 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
6085                 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
6086                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6087
6088                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6089                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6090                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6091                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6092                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6093                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6094 #endif
6095                 break;
6096         case RENDERPATH_GL13:
6097         case RENDERPATH_GL11:
6098                 break;
6099         }
6100 }
6101
6102 #define SKINFRAME_HASH 1024
6103
6104 typedef struct
6105 {
6106         int loadsequence; // incremented each level change
6107         memexpandablearray_t array;
6108         skinframe_t *hash[SKINFRAME_HASH];
6109 }
6110 r_skinframe_t;
6111 r_skinframe_t r_skinframe;
6112
6113 void R_SkinFrame_PrepareForPurge(void)
6114 {
6115         r_skinframe.loadsequence++;
6116         // wrap it without hitting zero
6117         if (r_skinframe.loadsequence >= 200)
6118                 r_skinframe.loadsequence = 1;
6119 }
6120
6121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6122 {
6123         if (!skinframe)
6124                 return;
6125         // mark the skinframe as used for the purging code
6126         skinframe->loadsequence = r_skinframe.loadsequence;
6127 }
6128
6129 void R_SkinFrame_Purge(void)
6130 {
6131         int i;
6132         skinframe_t *s;
6133         for (i = 0;i < SKINFRAME_HASH;i++)
6134         {
6135                 for (s = r_skinframe.hash[i];s;s = s->next)
6136                 {
6137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6138                         {
6139                                 if (s->merged == s->base)
6140                                         s->merged = NULL;
6141                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6142                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6143                                 R_PurgeTexture(s->merged);s->merged = NULL;
6144                                 R_PurgeTexture(s->base  );s->base   = NULL;
6145                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6146                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6147                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6148                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6149                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6150                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6151                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6152                                 s->loadsequence = 0;
6153                         }
6154                 }
6155         }
6156 }
6157
6158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6159         skinframe_t *item;
6160         char basename[MAX_QPATH];
6161
6162         Image_StripImageExtension(name, basename, sizeof(basename));
6163
6164         if( last == NULL ) {
6165                 int hashindex;
6166                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6167                 item = r_skinframe.hash[hashindex];
6168         } else {
6169                 item = last->next;
6170         }
6171
6172         // linearly search through the hash bucket
6173         for( ; item ; item = item->next ) {
6174                 if( !strcmp( item->basename, basename ) ) {
6175                         return item;
6176                 }
6177         }
6178         return NULL;
6179 }
6180
6181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6182 {
6183         skinframe_t *item;
6184         int hashindex;
6185         char basename[MAX_QPATH];
6186
6187         Image_StripImageExtension(name, basename, sizeof(basename));
6188
6189         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6190         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6191                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6192                         break;
6193
6194         if (!item) {
6195                 rtexture_t *dyntexture;
6196                 // check whether its a dynamic texture
6197                 dyntexture = CL_GetDynTexture( basename );
6198                 if (!add && !dyntexture)
6199                         return NULL;
6200                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6201                 memset(item, 0, sizeof(*item));
6202                 strlcpy(item->basename, basename, sizeof(item->basename));
6203                 item->base = dyntexture; // either NULL or dyntexture handle
6204                 item->textureflags = textureflags;
6205                 item->comparewidth = comparewidth;
6206                 item->compareheight = compareheight;
6207                 item->comparecrc = comparecrc;
6208                 item->next = r_skinframe.hash[hashindex];
6209                 r_skinframe.hash[hashindex] = item;
6210         }
6211         else if( item->base == NULL )
6212         {
6213                 rtexture_t *dyntexture;
6214                 // check whether its a dynamic texture
6215                 // 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]
6216                 dyntexture = CL_GetDynTexture( basename );
6217                 item->base = dyntexture; // either NULL or dyntexture handle
6218         }
6219
6220         R_SkinFrame_MarkUsed(item);
6221         return item;
6222 }
6223
6224 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6225         { \
6226                 unsigned long long avgcolor[5], wsum; \
6227                 int pix, comp, w; \
6228                 avgcolor[0] = 0; \
6229                 avgcolor[1] = 0; \
6230                 avgcolor[2] = 0; \
6231                 avgcolor[3] = 0; \
6232                 avgcolor[4] = 0; \
6233                 wsum = 0; \
6234                 for(pix = 0; pix < cnt; ++pix) \
6235                 { \
6236                         w = 0; \
6237                         for(comp = 0; comp < 3; ++comp) \
6238                                 w += getpixel; \
6239                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6240                         { \
6241                                 ++wsum; \
6242                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6243                                 w = getpixel; \
6244                                 for(comp = 0; comp < 3; ++comp) \
6245                                         avgcolor[comp] += getpixel * w; \
6246                                 avgcolor[3] += w; \
6247                         } \
6248                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6249                         avgcolor[4] += getpixel; \
6250                 } \
6251                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6252                         avgcolor[3] = 1; \
6253                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6254                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6255                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6256                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6257         }
6258
6259 extern cvar_t gl_picmip;
6260 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6261 {
6262         int j;
6263         unsigned char *pixels;
6264         unsigned char *bumppixels;
6265         unsigned char *basepixels = NULL;
6266         int basepixels_width = 0;
6267         int basepixels_height = 0;
6268         skinframe_t *skinframe;
6269         rtexture_t *ddsbase = NULL;
6270         qboolean ddshasalpha = false;
6271         float ddsavgcolor[4];
6272         char basename[MAX_QPATH];
6273         int miplevel = R_PicmipForFlags(textureflags);
6274         int savemiplevel = miplevel;
6275         int mymiplevel;
6276
6277         if (cls.state == ca_dedicated)
6278                 return NULL;
6279
6280         // return an existing skinframe if already loaded
6281         // if loading of the first image fails, don't make a new skinframe as it
6282         // would cause all future lookups of this to be missing
6283         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6284         if (skinframe && skinframe->base)
6285                 return skinframe;
6286
6287         Image_StripImageExtension(name, basename, sizeof(basename));
6288
6289         // check for DDS texture file first
6290         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6291         {
6292                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6293                 if (basepixels == NULL)
6294                         return NULL;
6295         }
6296
6297         // FIXME handle miplevel
6298
6299         if (developer_loading.integer)
6300                 Con_Printf("loading skin \"%s\"\n", name);
6301
6302         // we've got some pixels to store, so really allocate this new texture now
6303         if (!skinframe)
6304                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6305         skinframe->stain = NULL;
6306         skinframe->merged = NULL;
6307         skinframe->base = NULL;
6308         skinframe->pants = NULL;
6309         skinframe->shirt = NULL;
6310         skinframe->nmap = NULL;
6311         skinframe->gloss = NULL;
6312         skinframe->glow = NULL;
6313         skinframe->fog = NULL;
6314         skinframe->reflect = NULL;
6315         skinframe->hasalpha = false;
6316
6317         if (ddsbase)
6318         {
6319                 skinframe->base = ddsbase;
6320                 skinframe->hasalpha = ddshasalpha;
6321                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6322                 if (r_loadfog && skinframe->hasalpha)
6323                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6324                 //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]);
6325         }
6326         else
6327         {
6328                 basepixels_width = image_width;
6329                 basepixels_height = image_height;
6330                 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);
6331                 if (textureflags & TEXF_ALPHA)
6332                 {
6333                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6334                         {
6335                                 if (basepixels[j] < 255)
6336                                 {
6337                                         skinframe->hasalpha = true;
6338                                         break;
6339                                 }
6340                         }
6341                         if (r_loadfog && skinframe->hasalpha)
6342                         {
6343                                 // has transparent pixels
6344                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6345                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6346                                 {
6347                                         pixels[j+0] = 255;
6348                                         pixels[j+1] = 255;
6349                                         pixels[j+2] = 255;
6350                                         pixels[j+3] = basepixels[j+3];
6351                                 }
6352                                 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);
6353                                 Mem_Free(pixels);
6354                         }
6355                 }
6356                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6357                 //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]);
6358                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6359                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6360                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6361                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6362         }
6363
6364         if (r_loaddds)
6365         {
6366                 mymiplevel = savemiplevel;
6367                 if (r_loadnormalmap)
6368                         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);
6369                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6370                 if (r_loadgloss)
6371                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6372                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6373                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6374                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6375         }
6376
6377         // _norm is the name used by tenebrae and has been adopted as standard
6378         if (r_loadnormalmap && skinframe->nmap == NULL)
6379         {
6380                 mymiplevel = savemiplevel;
6381                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6382                 {
6383                         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);
6384                         Mem_Free(pixels);
6385                         pixels = NULL;
6386                 }
6387                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6388                 {
6389                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6390                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6391                         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);
6392                         Mem_Free(pixels);
6393                         Mem_Free(bumppixels);
6394                 }
6395                 else if (r_shadow_bumpscale_basetexture.value > 0)
6396                 {
6397                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6398                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6399                         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);
6400                         Mem_Free(pixels);
6401                 }
6402                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6403                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6404         }
6405
6406         // _luma is supported only for tenebrae compatibility
6407         // _glow is the preferred name
6408         mymiplevel = savemiplevel;
6409         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))))
6410         {
6411                 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);
6412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6413                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6414                 Mem_Free(pixels);pixels = NULL;
6415         }
6416
6417         mymiplevel = savemiplevel;
6418         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6419         {
6420                 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);
6421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6422                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6423                 Mem_Free(pixels);
6424                 pixels = NULL;
6425         }
6426
6427         mymiplevel = savemiplevel;
6428         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6429         {
6430                 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);
6431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6432                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6433                 Mem_Free(pixels);
6434                 pixels = NULL;
6435         }
6436
6437         mymiplevel = savemiplevel;
6438         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6439         {
6440                 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);
6441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6442                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6443                 Mem_Free(pixels);
6444                 pixels = NULL;
6445         }
6446
6447         mymiplevel = savemiplevel;
6448         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6449         {
6450                 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);
6451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6452                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6453                 Mem_Free(pixels);
6454                 pixels = NULL;
6455         }
6456
6457         if (basepixels)
6458                 Mem_Free(basepixels);
6459
6460         return skinframe;
6461 }
6462
6463 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6464 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6465 {
6466         int i;
6467         unsigned char *temp1, *temp2;
6468         skinframe_t *skinframe;
6469
6470         if (cls.state == ca_dedicated)
6471                 return NULL;
6472
6473         // if already loaded just return it, otherwise make a new skinframe
6474         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6475         if (skinframe && skinframe->base)
6476                 return skinframe;
6477
6478         skinframe->stain = NULL;
6479         skinframe->merged = NULL;
6480         skinframe->base = NULL;
6481         skinframe->pants = NULL;
6482         skinframe->shirt = NULL;
6483         skinframe->nmap = NULL;
6484         skinframe->gloss = NULL;
6485         skinframe->glow = NULL;
6486         skinframe->fog = NULL;
6487         skinframe->reflect = NULL;
6488         skinframe->hasalpha = false;
6489
6490         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6491         if (!skindata)
6492                 return NULL;
6493
6494         if (developer_loading.integer)
6495                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6496
6497         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6498         {
6499                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6500                 temp2 = temp1 + width * height * 4;
6501                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6502                 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);
6503                 Mem_Free(temp1);
6504         }
6505         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6506         if (textureflags & TEXF_ALPHA)
6507         {
6508                 for (i = 3;i < width * height * 4;i += 4)
6509                 {
6510                         if (skindata[i] < 255)
6511                         {
6512                                 skinframe->hasalpha = true;
6513                                 break;
6514                         }
6515                 }
6516                 if (r_loadfog && skinframe->hasalpha)
6517                 {
6518                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6519                         memcpy(fogpixels, skindata, width * height * 4);
6520                         for (i = 0;i < width * height * 4;i += 4)
6521                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6522                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6523                         Mem_Free(fogpixels);
6524                 }
6525         }
6526
6527         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6528         //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]);
6529
6530         return skinframe;
6531 }
6532
6533 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6534 {
6535         int i;
6536         int featuresmask;
6537         skinframe_t *skinframe;
6538
6539         if (cls.state == ca_dedicated)
6540                 return NULL;
6541
6542         // if already loaded just return it, otherwise make a new skinframe
6543         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6544         if (skinframe && skinframe->base)
6545                 return skinframe;
6546
6547         skinframe->stain = NULL;
6548         skinframe->merged = NULL;
6549         skinframe->base = NULL;
6550         skinframe->pants = NULL;
6551         skinframe->shirt = NULL;
6552         skinframe->nmap = NULL;
6553         skinframe->gloss = NULL;
6554         skinframe->glow = NULL;
6555         skinframe->fog = NULL;
6556         skinframe->reflect = NULL;
6557         skinframe->hasalpha = false;
6558
6559         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6560         if (!skindata)
6561                 return NULL;
6562
6563         if (developer_loading.integer)
6564                 Con_Printf("loading quake skin \"%s\"\n", name);
6565
6566         // 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)
6567         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height);
6568         memcpy(skinframe->qpixels, skindata, width*height);
6569         skinframe->qwidth = width;
6570         skinframe->qheight = height;
6571
6572         featuresmask = 0;
6573         for (i = 0;i < width * height;i++)
6574                 featuresmask |= palette_featureflags[skindata[i]];
6575
6576         skinframe->hasalpha = false;
6577         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6578         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6579         skinframe->qgeneratemerged = true;
6580         skinframe->qgeneratebase = skinframe->qhascolormapping;
6581         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6582
6583         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6584         //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]);
6585
6586         return skinframe;
6587 }
6588
6589 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6590 {
6591         int width;
6592         int height;
6593         unsigned char *skindata;
6594
6595         if (!skinframe->qpixels)
6596                 return;
6597
6598         if (!skinframe->qhascolormapping)
6599                 colormapped = false;
6600
6601         if (colormapped)
6602         {
6603                 if (!skinframe->qgeneratebase)
6604                         return;
6605         }
6606         else
6607         {
6608                 if (!skinframe->qgeneratemerged)
6609                         return;
6610         }
6611
6612         width = skinframe->qwidth;
6613         height = skinframe->qheight;
6614         skindata = skinframe->qpixels;
6615
6616         if (skinframe->qgeneratenmap)
6617         {
6618                 unsigned char *temp1, *temp2;
6619                 skinframe->qgeneratenmap = false;
6620                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6621                 temp2 = temp1 + width * height * 4;
6622                 // use either a custom palette or the quake palette
6623                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6624                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6625                 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);
6626                 Mem_Free(temp1);
6627         }
6628
6629         if (skinframe->qgenerateglow)
6630         {
6631                 skinframe->qgenerateglow = false;
6632                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6633         }
6634
6635         if (colormapped)
6636         {
6637                 skinframe->qgeneratebase = false;
6638                 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);
6639                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6640                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6641         }
6642         else
6643         {
6644                 skinframe->qgeneratemerged = false;
6645                 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);
6646         }
6647
6648         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6649         {
6650                 Mem_Free(skinframe->qpixels);
6651                 skinframe->qpixels = NULL;
6652         }
6653 }
6654
6655 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)
6656 {
6657         int i;
6658         skinframe_t *skinframe;
6659
6660         if (cls.state == ca_dedicated)
6661                 return NULL;
6662
6663         // if already loaded just return it, otherwise make a new skinframe
6664         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6665         if (skinframe && skinframe->base)
6666                 return skinframe;
6667
6668         skinframe->stain = NULL;
6669         skinframe->merged = NULL;
6670         skinframe->base = NULL;
6671         skinframe->pants = NULL;
6672         skinframe->shirt = NULL;
6673         skinframe->nmap = NULL;
6674         skinframe->gloss = NULL;
6675         skinframe->glow = NULL;
6676         skinframe->fog = NULL;
6677         skinframe->reflect = NULL;
6678         skinframe->hasalpha = false;
6679
6680         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6681         if (!skindata)
6682                 return NULL;
6683
6684         if (developer_loading.integer)
6685                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6686
6687         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6688         if (textureflags & TEXF_ALPHA)
6689         {
6690                 for (i = 0;i < width * height;i++)
6691                 {
6692                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6693                         {
6694                                 skinframe->hasalpha = true;
6695                                 break;
6696                         }
6697                 }
6698                 if (r_loadfog && skinframe->hasalpha)
6699                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6700         }
6701
6702         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6703         //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]);
6704
6705         return skinframe;
6706 }
6707
6708 skinframe_t *R_SkinFrame_LoadMissing(void)
6709 {
6710         skinframe_t *skinframe;
6711
6712         if (cls.state == ca_dedicated)
6713                 return NULL;
6714
6715         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6716         skinframe->stain = NULL;
6717         skinframe->merged = NULL;
6718         skinframe->base = NULL;
6719         skinframe->pants = NULL;
6720         skinframe->shirt = NULL;
6721         skinframe->nmap = NULL;
6722         skinframe->gloss = NULL;
6723         skinframe->glow = NULL;
6724         skinframe->fog = NULL;
6725         skinframe->reflect = NULL;
6726         skinframe->hasalpha = false;
6727
6728         skinframe->avgcolor[0] = rand() / RAND_MAX;
6729         skinframe->avgcolor[1] = rand() / RAND_MAX;
6730         skinframe->avgcolor[2] = rand() / RAND_MAX;
6731         skinframe->avgcolor[3] = 1;
6732
6733         return skinframe;
6734 }
6735
6736 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6737 typedef struct suffixinfo_s
6738 {
6739         const char *suffix;
6740         qboolean flipx, flipy, flipdiagonal;
6741 }
6742 suffixinfo_t;
6743 static suffixinfo_t suffix[3][6] =
6744 {
6745         {
6746                 {"px",   false, false, false},
6747                 {"nx",   false, false, false},
6748                 {"py",   false, false, false},
6749                 {"ny",   false, false, false},
6750                 {"pz",   false, false, false},
6751                 {"nz",   false, false, false}
6752         },
6753         {
6754                 {"posx", false, false, false},
6755                 {"negx", false, false, false},
6756                 {"posy", false, false, false},
6757                 {"negy", false, false, false},
6758                 {"posz", false, false, false},
6759                 {"negz", false, false, false}
6760         },
6761         {
6762                 {"rt",    true, false,  true},
6763                 {"lf",   false,  true,  true},
6764                 {"ft",    true,  true, false},
6765                 {"bk",   false, false, false},
6766                 {"up",    true, false,  true},
6767                 {"dn",    true, false,  true}
6768         }
6769 };
6770
6771 static int componentorder[4] = {0, 1, 2, 3};
6772
6773 rtexture_t *R_LoadCubemap(const char *basename)
6774 {
6775         int i, j, cubemapsize;
6776         unsigned char *cubemappixels, *image_buffer;
6777         rtexture_t *cubemaptexture;
6778         char name[256];
6779         // must start 0 so the first loadimagepixels has no requested width/height
6780         cubemapsize = 0;
6781         cubemappixels = NULL;
6782         cubemaptexture = NULL;
6783         // keep trying different suffix groups (posx, px, rt) until one loads
6784         for (j = 0;j < 3 && !cubemappixels;j++)
6785         {
6786                 // load the 6 images in the suffix group
6787                 for (i = 0;i < 6;i++)
6788                 {
6789                         // generate an image name based on the base and and suffix
6790                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6791                         // load it
6792                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6793                         {
6794                                 // an image loaded, make sure width and height are equal
6795                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6796                                 {
6797                                         // if this is the first image to load successfully, allocate the cubemap memory
6798                                         if (!cubemappixels && image_width >= 1)
6799                                         {
6800                                                 cubemapsize = image_width;
6801                                                 // note this clears to black, so unavailable sides are black
6802                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6803                                         }
6804                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6805                                         if (cubemappixels)
6806                                                 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);
6807                                 }
6808                                 else
6809                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6810                                 // free the image
6811                                 Mem_Free(image_buffer);
6812                         }
6813                 }
6814         }
6815         // if a cubemap loaded, upload it
6816         if (cubemappixels)
6817         {
6818                 if (developer_loading.integer)
6819                         Con_Printf("loading cubemap \"%s\"\n", basename);
6820
6821                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6822                 Mem_Free(cubemappixels);
6823         }
6824         else
6825         {
6826                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6827                 if (developer_loading.integer)
6828                 {
6829                         Con_Printf("(tried tried images ");
6830                         for (j = 0;j < 3;j++)
6831                                 for (i = 0;i < 6;i++)
6832                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6833                         Con_Print(" and was unable to find any of them).\n");
6834                 }
6835         }
6836         return cubemaptexture;
6837 }
6838
6839 rtexture_t *R_GetCubemap(const char *basename)
6840 {
6841         int i;
6842         for (i = 0;i < r_texture_numcubemaps;i++)
6843                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6844                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6845         if (i >= MAX_CUBEMAPS)
6846                 return r_texture_whitecube;
6847         r_texture_numcubemaps++;
6848         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6849         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6850         return r_texture_cubemaps[i].texture;
6851 }
6852
6853 void R_FreeCubemaps(void)
6854 {
6855         int i;
6856         for (i = 0;i < r_texture_numcubemaps;i++)
6857         {
6858                 if (developer_loading.integer)
6859                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6860                 if (r_texture_cubemaps[i].texture)
6861                         R_FreeTexture(r_texture_cubemaps[i].texture);
6862         }
6863         r_texture_numcubemaps = 0;
6864 }
6865
6866 void R_Main_FreeViewCache(void)
6867 {
6868         if (r_refdef.viewcache.entityvisible)
6869                 Mem_Free(r_refdef.viewcache.entityvisible);
6870         if (r_refdef.viewcache.world_pvsbits)
6871                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6872         if (r_refdef.viewcache.world_leafvisible)
6873                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6874         if (r_refdef.viewcache.world_surfacevisible)
6875                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6876         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6877 }
6878
6879 void R_Main_ResizeViewCache(void)
6880 {
6881         int numentities = r_refdef.scene.numentities;
6882         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6883         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6884         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6885         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6886         if (r_refdef.viewcache.maxentities < numentities)
6887         {
6888                 r_refdef.viewcache.maxentities = numentities;
6889                 if (r_refdef.viewcache.entityvisible)
6890                         Mem_Free(r_refdef.viewcache.entityvisible);
6891                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6892         }
6893         if (r_refdef.viewcache.world_numclusters != numclusters)
6894         {
6895                 r_refdef.viewcache.world_numclusters = numclusters;
6896                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6897                 if (r_refdef.viewcache.world_pvsbits)
6898                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6899                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6900         }
6901         if (r_refdef.viewcache.world_numleafs != numleafs)
6902         {
6903                 r_refdef.viewcache.world_numleafs = numleafs;
6904                 if (r_refdef.viewcache.world_leafvisible)
6905                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6906                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6907         }
6908         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6909         {
6910                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6911                 if (r_refdef.viewcache.world_surfacevisible)
6912                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6913                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6914         }
6915 }
6916
6917 extern rtexture_t *loadingscreentexture;
6918 void gl_main_start(void)
6919 {
6920         loadingscreentexture = NULL;
6921         r_texture_blanknormalmap = NULL;
6922         r_texture_white = NULL;
6923         r_texture_grey128 = NULL;
6924         r_texture_black = NULL;
6925         r_texture_whitecube = NULL;
6926         r_texture_normalizationcube = NULL;
6927         r_texture_fogattenuation = NULL;
6928         r_texture_fogheighttexture = NULL;
6929         r_texture_gammaramps = NULL;
6930         r_texture_numcubemaps = 0;
6931
6932         r_loaddds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_load.integer;
6933         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6934
6935         switch(vid.renderpath)
6936         {
6937         case RENDERPATH_GL20:
6938         case RENDERPATH_CGGL:
6939         case RENDERPATH_D3D9:
6940         case RENDERPATH_D3D10:
6941         case RENDERPATH_D3D11:
6942                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6943                 Cvar_SetValueQuick(&gl_combine, 1);
6944                 Cvar_SetValueQuick(&r_glsl, 1);
6945                 r_loadnormalmap = true;
6946                 r_loadgloss = true;
6947                 r_loadfog = false;
6948                 break;
6949         case RENDERPATH_GL13:
6950                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6951                 Cvar_SetValueQuick(&gl_combine, 1);
6952                 Cvar_SetValueQuick(&r_glsl, 0);
6953                 r_loadnormalmap = false;
6954                 r_loadgloss = false;
6955                 r_loadfog = true;
6956                 break;
6957         case RENDERPATH_GL11:
6958                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6959                 Cvar_SetValueQuick(&gl_combine, 0);
6960                 Cvar_SetValueQuick(&r_glsl, 0);
6961                 r_loadnormalmap = false;
6962                 r_loadgloss = false;
6963                 r_loadfog = true;
6964                 break;
6965         }
6966
6967         R_AnimCache_Free();
6968         R_FrameData_Reset();
6969
6970         r_numqueries = 0;
6971         r_maxqueries = 0;
6972         memset(r_queries, 0, sizeof(r_queries));
6973
6974         r_qwskincache = NULL;
6975         r_qwskincache_size = 0;
6976
6977         // set up r_skinframe loading system for textures
6978         memset(&r_skinframe, 0, sizeof(r_skinframe));
6979         r_skinframe.loadsequence = 1;
6980         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6981
6982         r_main_texturepool = R_AllocTexturePool();
6983         R_BuildBlankTextures();
6984         R_BuildNoTexture();
6985         if (vid.support.arb_texture_cube_map)
6986         {
6987                 R_BuildWhiteCube();
6988                 R_BuildNormalizationCube();
6989         }
6990         r_texture_fogattenuation = NULL;
6991         r_texture_fogheighttexture = NULL;
6992         r_texture_gammaramps = NULL;
6993         //r_texture_fogintensity = NULL;
6994         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6995         memset(&r_waterstate, 0, sizeof(r_waterstate));
6996         r_glsl_permutation = NULL;
6997         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6998         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6999         glslshaderstring = NULL;
7000 #ifdef SUPPORTCG
7001         r_cg_permutation = NULL;
7002         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7003         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7004         cgshaderstring = NULL;
7005 #endif
7006 #ifdef SUPPORTD3D
7007         r_hlsl_permutation = NULL;
7008         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7009         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7010         hlslshaderstring = NULL;
7011 #endif
7012         memset(&r_svbsp, 0, sizeof (r_svbsp));
7013
7014         r_refdef.fogmasktable_density = 0;
7015 }
7016
7017 void gl_main_shutdown(void)
7018 {
7019         R_AnimCache_Free();
7020         R_FrameData_Reset();
7021
7022         R_Main_FreeViewCache();
7023
7024         switch(vid.renderpath)
7025         {
7026         case RENDERPATH_GL11:
7027         case RENDERPATH_GL13:
7028         case RENDERPATH_GL20:
7029         case RENDERPATH_CGGL:
7030                 if (r_maxqueries)
7031                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7032                 break;
7033         case RENDERPATH_D3D9:
7034                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7035                 break;
7036         case RENDERPATH_D3D10:
7037                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7038                 break;
7039         case RENDERPATH_D3D11:
7040                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7041                 break;
7042         }
7043
7044         r_numqueries = 0;
7045         r_maxqueries = 0;
7046         memset(r_queries, 0, sizeof(r_queries));
7047
7048         r_qwskincache = NULL;
7049         r_qwskincache_size = 0;
7050
7051         // clear out the r_skinframe state
7052         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7053         memset(&r_skinframe, 0, sizeof(r_skinframe));
7054
7055         if (r_svbsp.nodes)
7056                 Mem_Free(r_svbsp.nodes);
7057         memset(&r_svbsp, 0, sizeof (r_svbsp));
7058         R_FreeTexturePool(&r_main_texturepool);
7059         loadingscreentexture = NULL;
7060         r_texture_blanknormalmap = NULL;
7061         r_texture_white = NULL;
7062         r_texture_grey128 = NULL;
7063         r_texture_black = NULL;
7064         r_texture_whitecube = NULL;
7065         r_texture_normalizationcube = NULL;
7066         r_texture_fogattenuation = NULL;
7067         r_texture_fogheighttexture = NULL;
7068         r_texture_gammaramps = NULL;
7069         r_texture_numcubemaps = 0;
7070         //r_texture_fogintensity = NULL;
7071         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7072         memset(&r_waterstate, 0, sizeof(r_waterstate));
7073         R_GLSL_Restart_f();
7074 }
7075
7076 extern void CL_ParseEntityLump(char *entitystring);
7077 void gl_main_newmap(void)
7078 {
7079         // FIXME: move this code to client
7080         char *entities, entname[MAX_QPATH];
7081         if (r_qwskincache)
7082                 Mem_Free(r_qwskincache);
7083         r_qwskincache = NULL;
7084         r_qwskincache_size = 0;
7085         if (cl.worldmodel)
7086         {
7087                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7088                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7089                 {
7090                         CL_ParseEntityLump(entities);
7091                         Mem_Free(entities);
7092                         return;
7093                 }
7094                 if (cl.worldmodel->brush.entities)
7095                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7096         }
7097         R_Main_FreeViewCache();
7098
7099         R_FrameData_Reset();
7100 }
7101
7102 void GL_Main_Init(void)
7103 {
7104         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7105
7106         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7107         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7108         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7109         if (gamemode == GAME_NEHAHRA)
7110         {
7111                 Cvar_RegisterVariable (&gl_fogenable);
7112                 Cvar_RegisterVariable (&gl_fogdensity);
7113                 Cvar_RegisterVariable (&gl_fogred);
7114                 Cvar_RegisterVariable (&gl_foggreen);
7115                 Cvar_RegisterVariable (&gl_fogblue);
7116                 Cvar_RegisterVariable (&gl_fogstart);
7117                 Cvar_RegisterVariable (&gl_fogend);
7118                 Cvar_RegisterVariable (&gl_skyclip);
7119         }
7120         Cvar_RegisterVariable(&r_motionblur);
7121         Cvar_RegisterVariable(&r_motionblur_maxblur);
7122         Cvar_RegisterVariable(&r_motionblur_bmin);
7123         Cvar_RegisterVariable(&r_motionblur_vmin);
7124         Cvar_RegisterVariable(&r_motionblur_vmax);
7125         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7126         Cvar_RegisterVariable(&r_motionblur_randomize);
7127         Cvar_RegisterVariable(&r_damageblur);
7128         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7129         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7130         Cvar_RegisterVariable(&r_equalize_entities_by);
7131         Cvar_RegisterVariable(&r_equalize_entities_to);
7132         Cvar_RegisterVariable(&r_depthfirst);
7133         Cvar_RegisterVariable(&r_useinfinitefarclip);
7134         Cvar_RegisterVariable(&r_farclip_base);
7135         Cvar_RegisterVariable(&r_farclip_world);
7136         Cvar_RegisterVariable(&r_nearclip);
7137         Cvar_RegisterVariable(&r_showbboxes);
7138         Cvar_RegisterVariable(&r_showsurfaces);
7139         Cvar_RegisterVariable(&r_showtris);
7140         Cvar_RegisterVariable(&r_shownormals);
7141         Cvar_RegisterVariable(&r_showlighting);
7142         Cvar_RegisterVariable(&r_showshadowvolumes);
7143         Cvar_RegisterVariable(&r_showcollisionbrushes);
7144         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7145         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7146         Cvar_RegisterVariable(&r_showdisabledepthtest);
7147         Cvar_RegisterVariable(&r_drawportals);
7148         Cvar_RegisterVariable(&r_drawentities);
7149         Cvar_RegisterVariable(&r_draw2d);
7150         Cvar_RegisterVariable(&r_drawworld);
7151         Cvar_RegisterVariable(&r_cullentities_trace);
7152         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7153         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7154         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7155         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7156         Cvar_RegisterVariable(&r_drawviewmodel);
7157         Cvar_RegisterVariable(&r_drawexteriormodel);
7158         Cvar_RegisterVariable(&r_speeds);
7159         Cvar_RegisterVariable(&r_fullbrights);
7160         Cvar_RegisterVariable(&r_wateralpha);
7161         Cvar_RegisterVariable(&r_dynamic);
7162         Cvar_RegisterVariable(&r_fullbright);
7163         Cvar_RegisterVariable(&r_shadows);
7164         Cvar_RegisterVariable(&r_shadows_darken);
7165         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7166         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7167         Cvar_RegisterVariable(&r_shadows_throwdistance);
7168         Cvar_RegisterVariable(&r_shadows_throwdirection);
7169         Cvar_RegisterVariable(&r_shadows_focus);
7170         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7171         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7172         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7173         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7174         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7175         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7176         Cvar_RegisterVariable(&r_fog_exp2);
7177         Cvar_RegisterVariable(&r_drawfog);
7178         Cvar_RegisterVariable(&r_transparentdepthmasking);
7179         Cvar_RegisterVariable(&r_texture_dds_load);
7180         Cvar_RegisterVariable(&r_texture_dds_save);
7181         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7182         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7183         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7184         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7185         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7186         Cvar_RegisterVariable(&r_textureunits);
7187         Cvar_RegisterVariable(&gl_combine);
7188         Cvar_RegisterVariable(&r_glsl);
7189         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7190         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7191         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7192         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7193         Cvar_RegisterVariable(&r_glsl_postprocess);
7194         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7195         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7196         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7197         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7198         Cvar_RegisterVariable(&r_water);
7199         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7200         Cvar_RegisterVariable(&r_water_clippingplanebias);
7201         Cvar_RegisterVariable(&r_water_refractdistort);
7202         Cvar_RegisterVariable(&r_water_reflectdistort);
7203         Cvar_RegisterVariable(&r_lerpsprites);
7204         Cvar_RegisterVariable(&r_lerpmodels);
7205         Cvar_RegisterVariable(&r_lerplightstyles);
7206         Cvar_RegisterVariable(&r_waterscroll);
7207         Cvar_RegisterVariable(&r_bloom);
7208         Cvar_RegisterVariable(&r_bloom_colorscale);
7209         Cvar_RegisterVariable(&r_bloom_brighten);
7210         Cvar_RegisterVariable(&r_bloom_blur);
7211         Cvar_RegisterVariable(&r_bloom_resolution);
7212         Cvar_RegisterVariable(&r_bloom_colorexponent);
7213         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7214         Cvar_RegisterVariable(&r_hdr);
7215         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7216         Cvar_RegisterVariable(&r_hdr_glowintensity);
7217         Cvar_RegisterVariable(&r_hdr_range);
7218         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7219         Cvar_RegisterVariable(&developer_texturelogging);
7220         Cvar_RegisterVariable(&gl_lightmaps);
7221         Cvar_RegisterVariable(&r_test);
7222         Cvar_RegisterVariable(&r_glsl_saturation);
7223         Cvar_RegisterVariable(&r_framedatasize);
7224         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7225                 Cvar_SetValue("r_fullbrights", 0);
7226         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7227
7228         Cvar_RegisterVariable(&r_track_sprites);
7229         Cvar_RegisterVariable(&r_track_sprites_flags);
7230         Cvar_RegisterVariable(&r_track_sprites_scalew);
7231         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7232         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7233         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7234 }
7235
7236 extern void R_Textures_Init(void);
7237 extern void GL_Draw_Init(void);
7238 extern void GL_Main_Init(void);
7239 extern void R_Shadow_Init(void);
7240 extern void R_Sky_Init(void);
7241 extern void GL_Surf_Init(void);
7242 extern void R_Particles_Init(void);
7243 extern void R_Explosion_Init(void);
7244 extern void gl_backend_init(void);
7245 extern void Sbar_Init(void);
7246 extern void R_LightningBeams_Init(void);
7247 extern void Mod_RenderInit(void);
7248 extern void Font_Init(void);
7249
7250 void Render_Init(void)
7251 {
7252         gl_backend_init();
7253         R_Textures_Init();
7254         GL_Main_Init();
7255         Font_Init();
7256         GL_Draw_Init();
7257         R_Shadow_Init();
7258         R_Sky_Init();
7259         GL_Surf_Init();
7260         Sbar_Init();
7261         R_Particles_Init();
7262         R_Explosion_Init();
7263         R_LightningBeams_Init();
7264         Mod_RenderInit();
7265 }
7266
7267 /*
7268 ===============
7269 GL_Init
7270 ===============
7271 */
7272 extern char *ENGINE_EXTENSIONS;
7273 void GL_Init (void)
7274 {
7275         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7276         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7277         gl_version = (const char *)qglGetString(GL_VERSION);
7278         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7279
7280         if (!gl_extensions)
7281                 gl_extensions = "";
7282         if (!gl_platformextensions)
7283                 gl_platformextensions = "";
7284
7285         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7286         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7287         Con_Printf("GL_VERSION: %s\n", gl_version);
7288         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7289         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7290
7291         VID_CheckExtensions();
7292
7293         // LordHavoc: report supported extensions
7294         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7295
7296         // clear to black (loading plaque will be seen over this)
7297         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7298 }
7299
7300 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7301 {
7302         int i;
7303         mplane_t *p;
7304         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7305         {
7306                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7307                 if (i == 4)
7308                         continue;
7309                 p = r_refdef.view.frustum + i;
7310                 switch(p->signbits)
7311                 {
7312                 default:
7313                 case 0:
7314                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7315                                 return true;
7316                         break;
7317                 case 1:
7318                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7319                                 return true;
7320                         break;
7321                 case 2:
7322                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7323                                 return true;
7324                         break;
7325                 case 3:
7326                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7327                                 return true;
7328                         break;
7329                 case 4:
7330                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7331                                 return true;
7332                         break;
7333                 case 5:
7334                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7335                                 return true;
7336                         break;
7337                 case 6:
7338                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7339                                 return true;
7340                         break;
7341                 case 7:
7342                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7343                                 return true;
7344                         break;
7345                 }
7346         }
7347         return false;
7348 }
7349
7350 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7351 {
7352         int i;
7353         const mplane_t *p;
7354         for (i = 0;i < numplanes;i++)
7355         {
7356                 p = planes + i;
7357                 switch(p->signbits)
7358                 {
7359                 default:
7360                 case 0:
7361                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7362                                 return true;
7363                         break;
7364                 case 1:
7365                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7366                                 return true;
7367                         break;
7368                 case 2:
7369                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7370                                 return true;
7371                         break;
7372                 case 3:
7373                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7374                                 return true;
7375                         break;
7376                 case 4:
7377                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7378                                 return true;
7379                         break;
7380                 case 5:
7381                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7382                                 return true;
7383                         break;
7384                 case 6:
7385                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7386                                 return true;
7387                         break;
7388                 case 7:
7389                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7390                                 return true;
7391                         break;
7392                 }
7393         }
7394         return false;
7395 }
7396
7397 //==================================================================================
7398
7399 // LordHavoc: this stores temporary data used within the same frame
7400
7401 qboolean r_framedata_failed;
7402 static size_t r_framedata_size;
7403 static size_t r_framedata_current;
7404 static void *r_framedata_base;
7405
7406 void R_FrameData_Reset(void)
7407 {
7408         if (r_framedata_base)
7409                 Mem_Free(r_framedata_base);
7410         r_framedata_base = NULL;
7411         r_framedata_size = 0;
7412         r_framedata_current = 0;
7413         r_framedata_failed = false;
7414 }
7415
7416 void R_FrameData_NewFrame(void)
7417 {
7418         size_t wantedsize;
7419         if (r_framedata_failed)
7420                 Cvar_SetValueQuick(&r_framedatasize, r_framedatasize.value + 1.0f);
7421         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7422         wantedsize = bound(65536, wantedsize, 128*1024*1024);
7423         if (r_framedata_size != wantedsize)
7424         {
7425                 r_framedata_size = wantedsize;
7426                 if (r_framedata_base)
7427                         Mem_Free(r_framedata_base);
7428                 r_framedata_base = Mem_Alloc(r_main_mempool, r_framedata_size);
7429         }
7430         r_framedata_current = 0;
7431         r_framedata_failed = false;
7432 }
7433
7434 void *R_FrameData_Alloc(size_t size)
7435 {
7436         void *data;
7437
7438         // align to 16 byte boundary
7439         size = (size + 15) & ~15;
7440         data = (void *)((unsigned char*)r_framedata_base + r_framedata_current);
7441         r_framedata_current += size;
7442
7443         // check overflow
7444         if (r_framedata_current > r_framedata_size)
7445                 r_framedata_failed = true;
7446
7447         // return NULL on everything after a failure
7448         if (r_framedata_failed)
7449                 return NULL;
7450
7451         return data;
7452 }
7453
7454 void *R_FrameData_Store(size_t size, void *data)
7455 {
7456         void *d = R_FrameData_Alloc(size);
7457         if (d)
7458                 memcpy(d, data, size);
7459         return d;
7460 }
7461
7462 //==================================================================================
7463
7464 // LordHavoc: animcache originally written by Echon, rewritten since then
7465
7466 /**
7467  * Animation cache prevents re-generating mesh data for an animated model
7468  * multiple times in one frame for lighting, shadowing, reflections, etc.
7469  */
7470
7471 void R_AnimCache_Free(void)
7472 {
7473 }
7474
7475 void R_AnimCache_ClearCache(void)
7476 {
7477         int i;
7478         entity_render_t *ent;
7479
7480         for (i = 0;i < r_refdef.scene.numentities;i++)
7481         {
7482                 ent = r_refdef.scene.entities[i];
7483                 ent->animcache_vertex3f = NULL;
7484                 ent->animcache_normal3f = NULL;
7485                 ent->animcache_svector3f = NULL;
7486                 ent->animcache_tvector3f = NULL;
7487                 ent->animcache_vertexposition = NULL;
7488                 ent->animcache_vertexmesh = NULL;
7489                 ent->animcache_vertexpositionbuffer = NULL;
7490                 ent->animcache_vertexmeshbuffer = NULL;
7491         }
7492 }
7493
7494 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7495 {
7496         int i;
7497
7498         // identical memory layout, so no need to allocate...
7499         // this also provides the vertexposition structure to everything, e.g.
7500         // depth masked rendering currently uses it even if having separate
7501         // arrays
7502         // NOTE: get rid of this optimization if changing it to e.g. 4f
7503         ent->animcache_vertexposition = (r_vertexposition_t *)ent->animcache_vertex3f;
7504
7505         // TODO:
7506         // get rid of following uses of VERTEXPOSITION, change to the array:
7507         // R_DrawTextureSurfaceList_Sky if skyrendermasked
7508         // R_DrawSurface_TransparentCallback if r_transparentdepthmasking.integer
7509         // R_DrawTextureSurfaceList_DepthOnly
7510         // R_Q1BSP_DrawShadowMap
7511
7512         switch(vid.renderpath)
7513         {
7514         case RENDERPATH_GL20:
7515         case RENDERPATH_CGGL:
7516                 // need the meshbuffers if !gl_mesh_separatearrays.integer
7517                 if (gl_mesh_separatearrays.integer)
7518                         return;
7519                 break;
7520         case RENDERPATH_D3D9:
7521         case RENDERPATH_D3D10:
7522         case RENDERPATH_D3D11:
7523                 // always need the meshbuffers
7524                 break;
7525         case RENDERPATH_GL13:
7526         case RENDERPATH_GL11:
7527                 // never need the meshbuffers
7528                 return;
7529         }
7530
7531         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7532                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7533         /*
7534         if (!ent->animcache_vertexposition)
7535                 ent->animcache_vertexposition = (r_vertexposition_t *)R_FrameData_Alloc(sizeof(r_vertexposition_t)*numvertices);
7536         */
7537         if (ent->animcache_vertexposition)
7538         {
7539                 /*
7540                 for (i = 0;i < numvertices;i++)
7541                         memcpy(ent->animcache_vertexposition[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7542                 */
7543                 // TODO: upload vertex buffer?
7544         }
7545         if (ent->animcache_vertexmesh)
7546         {
7547                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7548                 for (i = 0;i < numvertices;i++)
7549                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7550                 if (ent->animcache_svector3f)
7551                         for (i = 0;i < numvertices;i++)
7552                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7553                 if (ent->animcache_tvector3f)
7554                         for (i = 0;i < numvertices;i++)
7555                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7556                 if (ent->animcache_normal3f)
7557                         for (i = 0;i < numvertices;i++)
7558                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7559                 // TODO: upload vertex buffer?
7560         }
7561 }
7562
7563 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7564 {
7565         dp_model_t *model = ent->model;
7566         int numvertices;
7567         // see if it's already cached this frame
7568         if (ent->animcache_vertex3f)
7569         {
7570                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7571                 if (wantnormals || wanttangents)
7572                 {
7573                         if (ent->animcache_normal3f)
7574                                 wantnormals = false;
7575                         if (ent->animcache_svector3f)
7576                                 wanttangents = false;
7577                         if (wantnormals || wanttangents)
7578                         {
7579                                 numvertices = model->surfmesh.num_vertices;
7580                                 if (wantnormals)
7581                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7582                                 if (wanttangents)
7583                                 {
7584                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7585                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7586                                 }
7587                                 if (!r_framedata_failed)
7588                                 {
7589                                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7590                                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7591                                 }
7592                         }
7593                 }
7594         }
7595         else
7596         {
7597                 // see if this ent is worth caching
7598                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7599                         return false;
7600                 // get some memory for this entity and generate mesh data
7601                 numvertices = model->surfmesh.num_vertices;
7602                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7603                 if (wantnormals)
7604                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7605                 if (wanttangents)
7606                 {
7607                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7608                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7609                 }
7610                 if (!r_framedata_failed)
7611                 {
7612                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7613                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7614                 }
7615         }
7616         return !r_framedata_failed;
7617 }
7618
7619 void R_AnimCache_CacheVisibleEntities(void)
7620 {
7621         int i;
7622         qboolean wantnormals = true;
7623         qboolean wanttangents = !r_showsurfaces.integer;
7624
7625         switch(vid.renderpath)
7626         {
7627         case RENDERPATH_GL20:
7628         case RENDERPATH_CGGL:
7629         case RENDERPATH_D3D9:
7630         case RENDERPATH_D3D10:
7631         case RENDERPATH_D3D11:
7632                 break;
7633         case RENDERPATH_GL13:
7634         case RENDERPATH_GL11:
7635                 wanttangents = false;
7636                 break;
7637         }
7638
7639         if (r_shownormals.integer)
7640                 wanttangents = wantnormals = true;
7641
7642         // TODO: thread this
7643         // NOTE: R_PrepareRTLights() also caches entities
7644
7645         for (i = 0;i < r_refdef.scene.numentities;i++)
7646                 if (r_refdef.viewcache.entityvisible[i])
7647                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7648 }
7649
7650 //==================================================================================
7651
7652 static void R_View_UpdateEntityLighting (void)
7653 {
7654         int i;
7655         entity_render_t *ent;
7656         vec3_t tempdiffusenormal, avg;
7657         vec_t f, fa, fd, fdd;
7658         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7659
7660         for (i = 0;i < r_refdef.scene.numentities;i++)
7661         {
7662                 ent = r_refdef.scene.entities[i];
7663
7664                 // skip unseen models
7665                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7666                         continue;
7667
7668                 // skip bsp models
7669                 if (ent->model && ent->model->brush.num_leafs)
7670                 {
7671                         // TODO: use modellight for r_ambient settings on world?
7672                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7673                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7674                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7675                         continue;
7676                 }
7677
7678                 // fetch the lighting from the worldmodel data
7679                 VectorClear(ent->modellight_ambient);
7680                 VectorClear(ent->modellight_diffuse);
7681                 VectorClear(tempdiffusenormal);
7682                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7683                 {
7684                         vec3_t org;
7685                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7686                         r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
7687                         if(ent->flags & RENDER_EQUALIZE)
7688                         {
7689                                 // first fix up ambient lighting...
7690                                 if(r_equalize_entities_minambient.value > 0)
7691                                 {
7692                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7693                                         if(fd > 0)
7694                                         {
7695                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7696                                                 if(fa < r_equalize_entities_minambient.value * fd)
7697                                                 {
7698                                                         // solve:
7699                                                         //   fa'/fd' = minambient
7700                                                         //   fa'+0.25*fd' = fa+0.25*fd
7701                                                         //   ...
7702                                                         //   fa' = fd' * minambient
7703                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7704                                                         //   ...
7705                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7706                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7707                                                         //   ...
7708                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7709                                                         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
7710                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7711                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7712                                                 }
7713                                         }
7714                                 }
7715
7716                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7717                                 {
7718                                         VectorMA(ent->modellight_ambient, 0.25f, ent->modellight_diffuse, avg);
7719                                         f = 0.299f * avg[0] + 0.587f * avg[1] + 0.114f * avg[2];
7720                                         if(f > 0)
7721                                         {
7722                                                 f = pow(f / r_equalize_entities_to.value, -r_equalize_entities_by.value);
7723                                                 VectorScale(ent->modellight_ambient, f, ent->modellight_ambient);
7724                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7725                                         }
7726                                 }
7727                         }
7728                 }
7729                 else // highly rare
7730                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7731
7732                 // move the light direction into modelspace coordinates for lighting code
7733                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7734                 if(VectorLength2(ent->modellight_lightdir) == 0)
7735                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7736                 VectorNormalize(ent->modellight_lightdir);
7737         }
7738 }
7739
7740 #define MAX_LINEOFSIGHTTRACES 64
7741
7742 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7743 {
7744         int i;
7745         vec3_t boxmins, boxmaxs;
7746         vec3_t start;
7747         vec3_t end;
7748         dp_model_t *model = r_refdef.scene.worldmodel;
7749
7750         if (!model || !model->brush.TraceLineOfSight)
7751                 return true;
7752
7753         // expand the box a little
7754         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7755         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7756         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7757         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7758         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7759         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7760
7761         // return true if eye is inside enlarged box
7762         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7763                 return true;
7764
7765         // try center
7766         VectorCopy(eye, start);
7767         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7768         if (model->brush.TraceLineOfSight(model, start, end))
7769                 return true;
7770
7771         // try various random positions
7772         for (i = 0;i < numsamples;i++)
7773         {
7774                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7775                 if (model->brush.TraceLineOfSight(model, start, end))
7776                         return true;
7777         }
7778
7779         return false;
7780 }
7781
7782
7783 static void R_View_UpdateEntityVisible (void)
7784 {
7785         int i;
7786         int renderimask;
7787         int samples;
7788         entity_render_t *ent;
7789
7790         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7791                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7792                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7793                 :                                                          RENDER_EXTERIORMODEL;
7794         if (!r_drawviewmodel.integer)
7795                 renderimask |= RENDER_VIEWMODEL;
7796         if (!r_drawexteriormodel.integer)
7797                 renderimask |= RENDER_EXTERIORMODEL;
7798         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7799         {
7800                 // worldmodel can check visibility
7801                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7802                 for (i = 0;i < r_refdef.scene.numentities;i++)
7803                 {
7804                         ent = r_refdef.scene.entities[i];
7805                         if (!(ent->flags & renderimask))
7806                         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)))
7807                         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))
7808                                 r_refdef.viewcache.entityvisible[i] = true;
7809                 }
7810                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7811                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7812                 {
7813                         for (i = 0;i < r_refdef.scene.numentities;i++)
7814                         {
7815                                 ent = r_refdef.scene.entities[i];
7816                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7817                                 {
7818                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7819                                         if (samples < 0)
7820                                                 continue; // temp entities do pvs only
7821                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7822                                                 ent->last_trace_visibility = realtime;
7823                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7824                                                 r_refdef.viewcache.entityvisible[i] = 0;
7825                                 }
7826                         }
7827                 }
7828         }
7829         else
7830         {
7831                 // no worldmodel or it can't check visibility
7832                 for (i = 0;i < r_refdef.scene.numentities;i++)
7833                 {
7834                         ent = r_refdef.scene.entities[i];
7835                         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));
7836                 }
7837         }
7838 }
7839
7840 /// only used if skyrendermasked, and normally returns false
7841 int R_DrawBrushModelsSky (void)
7842 {
7843         int i, sky;
7844         entity_render_t *ent;
7845
7846         sky = false;
7847         for (i = 0;i < r_refdef.scene.numentities;i++)
7848         {
7849                 if (!r_refdef.viewcache.entityvisible[i])
7850                         continue;
7851                 ent = r_refdef.scene.entities[i];
7852                 if (!ent->model || !ent->model->DrawSky)
7853                         continue;
7854                 ent->model->DrawSky(ent);
7855                 sky = true;
7856         }
7857         return sky;
7858 }
7859
7860 static void R_DrawNoModel(entity_render_t *ent);
7861 static void R_DrawModels(void)
7862 {
7863         int i;
7864         entity_render_t *ent;
7865
7866         for (i = 0;i < r_refdef.scene.numentities;i++)
7867         {
7868                 if (!r_refdef.viewcache.entityvisible[i])
7869                         continue;
7870                 ent = r_refdef.scene.entities[i];
7871                 r_refdef.stats.entities++;
7872                 if (ent->model && ent->model->Draw != NULL)
7873                         ent->model->Draw(ent);
7874                 else
7875                         R_DrawNoModel(ent);
7876         }
7877 }
7878
7879 static void R_DrawModelsDepth(void)
7880 {
7881         int i;
7882         entity_render_t *ent;
7883
7884         for (i = 0;i < r_refdef.scene.numentities;i++)
7885         {
7886                 if (!r_refdef.viewcache.entityvisible[i])
7887                         continue;
7888                 ent = r_refdef.scene.entities[i];
7889                 if (ent->model && ent->model->DrawDepth != NULL)
7890                         ent->model->DrawDepth(ent);
7891         }
7892 }
7893
7894 static void R_DrawModelsDebug(void)
7895 {
7896         int i;
7897         entity_render_t *ent;
7898
7899         for (i = 0;i < r_refdef.scene.numentities;i++)
7900         {
7901                 if (!r_refdef.viewcache.entityvisible[i])
7902                         continue;
7903                 ent = r_refdef.scene.entities[i];
7904                 if (ent->model && ent->model->DrawDebug != NULL)
7905                         ent->model->DrawDebug(ent);
7906         }
7907 }
7908
7909 static void R_DrawModelsAddWaterPlanes(void)
7910 {
7911         int i;
7912         entity_render_t *ent;
7913
7914         for (i = 0;i < r_refdef.scene.numentities;i++)
7915         {
7916                 if (!r_refdef.viewcache.entityvisible[i])
7917                         continue;
7918                 ent = r_refdef.scene.entities[i];
7919                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7920                         ent->model->DrawAddWaterPlanes(ent);
7921         }
7922 }
7923
7924 static void R_View_SetFrustum(void)
7925 {
7926         int i;
7927         double slopex, slopey;
7928         vec3_t forward, left, up, origin;
7929
7930         // we can't trust r_refdef.view.forward and friends in reflected scenes
7931         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7932
7933 #if 0
7934         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7935         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7936         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7937         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7938         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7939         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7940         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7941         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7942         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7943         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7944         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7945         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7946 #endif
7947
7948 #if 0
7949         zNear = r_refdef.nearclip;
7950         nudge = 1.0 - 1.0 / (1<<23);
7951         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7952         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7953         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7954         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7955         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7956         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7957         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7958         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7959 #endif
7960
7961
7962
7963 #if 0
7964         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7965         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7966         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7967         r_refdef.view.frustum[0].dist = m[15] - m[12];
7968
7969         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7970         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7971         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7972         r_refdef.view.frustum[1].dist = m[15] + m[12];
7973
7974         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7975         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7976         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7977         r_refdef.view.frustum[2].dist = m[15] - m[13];
7978
7979         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7980         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7981         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7982         r_refdef.view.frustum[3].dist = m[15] + m[13];
7983
7984         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7985         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7986         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7987         r_refdef.view.frustum[4].dist = m[15] - m[14];
7988
7989         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7990         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7991         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7992         r_refdef.view.frustum[5].dist = m[15] + m[14];
7993 #endif
7994
7995         if (r_refdef.view.useperspective)
7996         {
7997                 slopex = 1.0 / r_refdef.view.frustum_x;
7998                 slopey = 1.0 / r_refdef.view.frustum_y;
7999                 VectorMA(forward, -slopex, left, r_refdef.view.frustum[0].normal);
8000                 VectorMA(forward,  slopex, left, r_refdef.view.frustum[1].normal);
8001                 VectorMA(forward, -slopey, up  , r_refdef.view.frustum[2].normal);
8002                 VectorMA(forward,  slopey, up  , r_refdef.view.frustum[3].normal);
8003                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8004
8005                 // Leaving those out was a mistake, those were in the old code, and they
8006                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8007                 // I couldn't reproduce it after adding those normalizations. --blub
8008                 VectorNormalize(r_refdef.view.frustum[0].normal);
8009                 VectorNormalize(r_refdef.view.frustum[1].normal);
8010                 VectorNormalize(r_refdef.view.frustum[2].normal);
8011                 VectorNormalize(r_refdef.view.frustum[3].normal);
8012
8013                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8014                 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]);
8015                 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]);
8016                 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]);
8017                 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]);
8018
8019                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8020                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8021                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8022                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8023                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8024         }
8025         else
8026         {
8027                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8028                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8029                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8030                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8031                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8032                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8033                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8034                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8035                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8036                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8037         }
8038         r_refdef.view.numfrustumplanes = 5;
8039
8040         if (r_refdef.view.useclipplane)
8041         {
8042                 r_refdef.view.numfrustumplanes = 6;
8043                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8044         }
8045
8046         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8047                 PlaneClassify(r_refdef.view.frustum + i);
8048
8049         // LordHavoc: note to all quake engine coders, Quake had a special case
8050         // for 90 degrees which assumed a square view (wrong), so I removed it,
8051         // Quake2 has it disabled as well.
8052
8053         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8054         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8055         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8056         //PlaneClassify(&frustum[0]);
8057
8058         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8059         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8060         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8061         //PlaneClassify(&frustum[1]);
8062
8063         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8064         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8065         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8066         //PlaneClassify(&frustum[2]);
8067
8068         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8069         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8070         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8071         //PlaneClassify(&frustum[3]);
8072
8073         // nearclip plane
8074         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8075         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8076         //PlaneClassify(&frustum[4]);
8077 }
8078
8079 void R_View_Update(void)
8080 {
8081         R_Main_ResizeViewCache();
8082         R_View_SetFrustum();
8083         R_View_WorldVisibility(r_refdef.view.useclipplane);
8084         R_View_UpdateEntityVisible();
8085         R_View_UpdateEntityLighting();
8086 }
8087
8088 void R_SetupView(qboolean allowwaterclippingplane)
8089 {
8090         const float *customclipplane = NULL;
8091         float plane[4];
8092         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8093         {
8094                 // LordHavoc: couldn't figure out how to make this approach the
8095                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8096                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8097                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8098                         dist = r_refdef.view.clipplane.dist;
8099                 plane[0] = r_refdef.view.clipplane.normal[0];
8100                 plane[1] = r_refdef.view.clipplane.normal[1];
8101                 plane[2] = r_refdef.view.clipplane.normal[2];
8102                 plane[3] = dist;
8103                 customclipplane = plane;
8104         }
8105
8106         if (!r_refdef.view.useperspective)
8107                 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);
8108         else if (vid.stencil && r_useinfinitefarclip.integer)
8109                 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);
8110         else
8111                 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);
8112         R_SetViewport(&r_refdef.view.viewport);
8113 }
8114
8115 void R_EntityMatrix(const matrix4x4_t *matrix)
8116 {
8117         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8118         {
8119                 gl_modelmatrixchanged = false;
8120                 gl_modelmatrix = *matrix;
8121                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8122                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8123                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8124                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8125                 CHECKGLERROR
8126                 switch(vid.renderpath)
8127                 {
8128                 case RENDERPATH_D3D9:
8129 #ifdef SUPPORTD3D
8130                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8131                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8132 #endif
8133                         break;
8134                 case RENDERPATH_D3D10:
8135                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8136                         break;
8137                 case RENDERPATH_D3D11:
8138                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8139                         break;
8140                 case RENDERPATH_GL20:
8141                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8142                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8143                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8144                         break;
8145                 case RENDERPATH_CGGL:
8146 #ifdef SUPPORTCG
8147                         CHECKCGERROR
8148                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8149                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8150                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8151 #endif
8152                         break;
8153                 case RENDERPATH_GL13:
8154                 case RENDERPATH_GL11:
8155                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8156                         break;
8157                 }
8158         }
8159 }
8160
8161 void R_ResetViewRendering2D(void)
8162 {
8163         r_viewport_t viewport;
8164         DrawQ_Finish();
8165
8166         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8167         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);
8168         R_SetViewport(&viewport);
8169         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8170         GL_Color(1, 1, 1, 1);
8171         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8172         GL_BlendFunc(GL_ONE, GL_ZERO);
8173         GL_AlphaTest(false);
8174         GL_ScissorTest(false);
8175         GL_DepthMask(false);
8176         GL_DepthRange(0, 1);
8177         GL_DepthTest(false);
8178         GL_DepthFunc(GL_LEQUAL);
8179         R_EntityMatrix(&identitymatrix);
8180         R_Mesh_ResetTextureState();
8181         GL_PolygonOffset(0, 0);
8182         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8183         switch(vid.renderpath)
8184         {
8185         case RENDERPATH_GL11:
8186         case RENDERPATH_GL13:
8187         case RENDERPATH_GL20:
8188         case RENDERPATH_CGGL:
8189                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8190                 break;
8191         case RENDERPATH_D3D9:
8192         case RENDERPATH_D3D10:
8193         case RENDERPATH_D3D11:
8194                 break;
8195         }
8196         GL_CullFace(GL_NONE);
8197 }
8198
8199 void R_ResetViewRendering3D(void)
8200 {
8201         DrawQ_Finish();
8202
8203         R_SetupView(true);
8204         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8205         GL_Color(1, 1, 1, 1);
8206         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8207         GL_BlendFunc(GL_ONE, GL_ZERO);
8208         GL_AlphaTest(false);
8209         GL_ScissorTest(true);
8210         GL_DepthMask(true);
8211         GL_DepthRange(0, 1);
8212         GL_DepthTest(true);
8213         GL_DepthFunc(GL_LEQUAL);
8214         R_EntityMatrix(&identitymatrix);
8215         R_Mesh_ResetTextureState();
8216         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8217         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8218         switch(vid.renderpath)
8219         {
8220         case RENDERPATH_GL11:
8221         case RENDERPATH_GL13:
8222         case RENDERPATH_GL20:
8223         case RENDERPATH_CGGL:
8224                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8225                 break;
8226         case RENDERPATH_D3D9:
8227         case RENDERPATH_D3D10:
8228         case RENDERPATH_D3D11:
8229                 break;
8230         }
8231         GL_CullFace(r_refdef.view.cullface_back);
8232 }
8233
8234 /*
8235 ================
8236 R_RenderView_UpdateViewVectors
8237 ================
8238 */
8239 static void R_RenderView_UpdateViewVectors(void)
8240 {
8241         // break apart the view matrix into vectors for various purposes
8242         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8243         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8244         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8245         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8246         // make an inverted copy of the view matrix for tracking sprites
8247         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8248 }
8249
8250 void R_RenderScene(void);
8251 void R_RenderWaterPlanes(void);
8252
8253 static void R_Water_StartFrame(void)
8254 {
8255         int i;
8256         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8257         r_waterstate_waterplane_t *p;
8258
8259         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8260                 return;
8261
8262         switch(vid.renderpath)
8263         {
8264         case RENDERPATH_GL20:
8265         case RENDERPATH_CGGL:
8266         case RENDERPATH_D3D9:
8267         case RENDERPATH_D3D10:
8268         case RENDERPATH_D3D11:
8269                 break;
8270         case RENDERPATH_GL13:
8271         case RENDERPATH_GL11:
8272                 return;
8273         }
8274
8275         // set waterwidth and waterheight to the water resolution that will be
8276         // used (often less than the screen resolution for faster rendering)
8277         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8278         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8279
8280         // calculate desired texture sizes
8281         // can't use water if the card does not support the texture size
8282         if (!r_water.integer || r_showsurfaces.integer)
8283                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8284         else if (vid.support.arb_texture_non_power_of_two)
8285         {
8286                 texturewidth = waterwidth;
8287                 textureheight = waterheight;
8288                 camerawidth = waterwidth;
8289                 cameraheight = waterheight;
8290         }
8291         else
8292         {
8293                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8294                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8295                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8296                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8297         }
8298
8299         // allocate textures as needed
8300         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8301         {
8302                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8303                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8304                 {
8305                         if (p->texture_refraction)
8306                                 R_FreeTexture(p->texture_refraction);
8307                         p->texture_refraction = NULL;
8308                         if (p->texture_reflection)
8309                                 R_FreeTexture(p->texture_reflection);
8310                         p->texture_reflection = NULL;
8311                         if (p->texture_camera)
8312                                 R_FreeTexture(p->texture_camera);
8313                         p->texture_camera = NULL;
8314                 }
8315                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8316                 r_waterstate.texturewidth = texturewidth;
8317                 r_waterstate.textureheight = textureheight;
8318                 r_waterstate.camerawidth = camerawidth;
8319                 r_waterstate.cameraheight = cameraheight;
8320         }
8321
8322         if (r_waterstate.texturewidth)
8323         {
8324                 r_waterstate.enabled = true;
8325
8326                 // when doing a reduced render (HDR) we want to use a smaller area
8327                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8328                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8329
8330                 // set up variables that will be used in shader setup
8331                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8332                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8333                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8334                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8335         }
8336
8337         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8338         r_waterstate.numwaterplanes = 0;
8339 }
8340
8341 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8342 {
8343         int triangleindex, planeindex;
8344         const int *e;
8345         vec3_t vert[3];
8346         vec3_t normal;
8347         vec3_t center;
8348         mplane_t plane;
8349         int cam_ent;
8350         r_waterstate_waterplane_t *p;
8351         texture_t *t = R_GetCurrentTexture(surface->texture);
8352         cam_ent = t->camera_entity;
8353         if(!(t->currentmaterialflags & MATERIALFLAG_CAMERA))
8354                 cam_ent = 0;
8355
8356         // just use the first triangle with a valid normal for any decisions
8357         VectorClear(normal);
8358         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8359         {
8360                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8361                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8362                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8363                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8364                 if (VectorLength2(normal) >= 0.001)
8365                         break;
8366         }
8367
8368         VectorCopy(normal, plane.normal);
8369         VectorNormalize(plane.normal);
8370         plane.dist = DotProduct(vert[0], plane.normal);
8371         PlaneClassify(&plane);
8372         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8373         {
8374                 // skip backfaces (except if nocullface is set)
8375                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8376                         return;
8377                 VectorNegate(plane.normal, plane.normal);
8378                 plane.dist *= -1;
8379                 PlaneClassify(&plane);
8380         }
8381
8382
8383         // find a matching plane if there is one
8384         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8385                 if(p->camera_entity == t->camera_entity)
8386                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8387                                 break;
8388         if (planeindex >= r_waterstate.maxwaterplanes)
8389                 return; // nothing we can do, out of planes
8390
8391         // if this triangle does not fit any known plane rendered this frame, add one
8392         if (planeindex >= r_waterstate.numwaterplanes)
8393         {
8394                 // store the new plane
8395                 r_waterstate.numwaterplanes++;
8396                 p->plane = plane;
8397                 // clear materialflags and pvs
8398                 p->materialflags = 0;
8399                 p->pvsvalid = false;
8400                 p->camera_entity = t->camera_entity;
8401         }
8402         // merge this surface's materialflags into the waterplane
8403         p->materialflags |= t->currentmaterialflags;
8404         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8405         {
8406                 // merge this surface's PVS into the waterplane
8407                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8408                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8409                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8410                 {
8411                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8412                         p->pvsvalid = true;
8413                 }
8414         }
8415 }
8416
8417 static void R_Water_ProcessPlanes(void)
8418 {
8419         r_refdef_view_t originalview;
8420         r_refdef_view_t myview;
8421         int planeindex;
8422         r_waterstate_waterplane_t *p;
8423         vec3_t visorigin;
8424
8425         originalview = r_refdef.view;
8426
8427         // make sure enough textures are allocated
8428         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8429         {
8430                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8431                 {
8432                         if (!p->texture_refraction)
8433                                 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);
8434                         if (!p->texture_refraction)
8435                                 goto error;
8436                 }
8437                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8438                 {
8439                         if (!p->texture_camera)
8440                                 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);
8441                         if (!p->texture_camera)
8442                                 goto error;
8443                 }
8444
8445                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8446                 {
8447                         if (!p->texture_reflection)
8448                                 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);
8449                         if (!p->texture_reflection)
8450                                 goto error;
8451                 }
8452         }
8453
8454         // render views
8455         r_refdef.view = originalview;
8456         r_refdef.view.showdebug = false;
8457         r_refdef.view.width = r_waterstate.waterwidth;
8458         r_refdef.view.height = r_waterstate.waterheight;
8459         r_refdef.view.useclipplane = true;
8460         myview = r_refdef.view;
8461         r_waterstate.renderingscene = true;
8462         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8463         {
8464                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8465                 {
8466                         r_refdef.view = myview;
8467                         // render reflected scene and copy into texture
8468                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8469                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8470                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8471                         r_refdef.view.clipplane = p->plane;
8472                         // reverse the cullface settings for this render
8473                         r_refdef.view.cullface_front = GL_FRONT;
8474                         r_refdef.view.cullface_back = GL_BACK;
8475                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8476                         {
8477                                 r_refdef.view.usecustompvs = true;
8478                                 if (p->pvsvalid)
8479                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8480                                 else
8481                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8482                         }
8483
8484                         R_ResetViewRendering3D();
8485                         R_ClearScreen(r_refdef.fogenabled);
8486                         R_View_Update();
8487                         R_RenderScene();
8488
8489                         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);
8490                 }
8491
8492                 // render the normal view scene and copy into texture
8493                 // (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)
8494                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8495                 {
8496                         r_waterstate.renderingrefraction = true;
8497                         r_refdef.view = myview;
8498
8499                         r_refdef.view.clipplane = p->plane;
8500                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8501                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8502
8503                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8504                         {
8505                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8506                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8507                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8508                                 R_RenderView_UpdateViewVectors();
8509                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8510                                 {
8511                                         r_refdef.view.usecustompvs = true;
8512                                         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);
8513                                 }
8514                         }
8515
8516                         PlaneClassify(&r_refdef.view.clipplane);
8517
8518                         R_ResetViewRendering3D();
8519                         R_ClearScreen(r_refdef.fogenabled);
8520                         R_View_Update();
8521                         R_RenderScene();
8522
8523                         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);
8524                         r_waterstate.renderingrefraction = false;
8525                 }
8526                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8527                 {
8528                         r_refdef.view = myview;
8529
8530                         r_refdef.view.clipplane = p->plane;
8531                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8532                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8533
8534                         r_refdef.view.width = r_waterstate.camerawidth;
8535                         r_refdef.view.height = r_waterstate.cameraheight;
8536                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8537                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8538
8539                         if(p->camera_entity)
8540                         {
8541                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8542                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8543                         }
8544
8545                         // reverse the cullface settings for this render
8546                         r_refdef.view.cullface_front = GL_FRONT;
8547                         r_refdef.view.cullface_back = GL_BACK;
8548                         // also reverse the view matrix
8549                         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
8550                         R_RenderView_UpdateViewVectors();
8551                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8552                         {
8553                                 r_refdef.view.usecustompvs = true;
8554                                 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);
8555                         }
8556                         
8557                         // camera needs no clipplane
8558                         r_refdef.view.useclipplane = false;
8559
8560                         PlaneClassify(&r_refdef.view.clipplane);
8561
8562                         R_ResetViewRendering3D();
8563                         R_ClearScreen(r_refdef.fogenabled);
8564                         R_View_Update();
8565                         R_RenderScene();
8566
8567                         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);
8568                         r_waterstate.renderingrefraction = false;
8569                 }
8570
8571         }
8572         r_waterstate.renderingscene = false;
8573         r_refdef.view = originalview;
8574         R_ResetViewRendering3D();
8575         R_ClearScreen(r_refdef.fogenabled);
8576         R_View_Update();
8577         return;
8578 error:
8579         r_refdef.view = originalview;
8580         r_waterstate.renderingscene = false;
8581         Cvar_SetValueQuick(&r_water, 0);
8582         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8583         return;
8584 }
8585
8586 void R_Bloom_StartFrame(void)
8587 {
8588         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8589
8590         switch(vid.renderpath)
8591         {
8592         case RENDERPATH_GL20:
8593         case RENDERPATH_CGGL:
8594         case RENDERPATH_D3D9:
8595         case RENDERPATH_D3D10:
8596         case RENDERPATH_D3D11:
8597                 break;
8598         case RENDERPATH_GL13:
8599         case RENDERPATH_GL11:
8600                 return;
8601         }
8602
8603         // set bloomwidth and bloomheight to the bloom resolution that will be
8604         // used (often less than the screen resolution for faster rendering)
8605         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8606         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8607         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8608         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8609         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8610
8611         // calculate desired texture sizes
8612         if (vid.support.arb_texture_non_power_of_two)
8613         {
8614                 screentexturewidth = r_refdef.view.width;
8615                 screentextureheight = r_refdef.view.height;
8616                 bloomtexturewidth = r_bloomstate.bloomwidth;
8617                 bloomtextureheight = r_bloomstate.bloomheight;
8618         }
8619         else
8620         {
8621                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8622                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8623                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8624                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8625         }
8626
8627         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))
8628         {
8629                 Cvar_SetValueQuick(&r_hdr, 0);
8630                 Cvar_SetValueQuick(&r_bloom, 0);
8631                 Cvar_SetValueQuick(&r_motionblur, 0);
8632                 Cvar_SetValueQuick(&r_damageblur, 0);
8633         }
8634
8635         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)))
8636                 screentexturewidth = screentextureheight = 0;
8637         if (!r_hdr.integer && !r_bloom.integer)
8638                 bloomtexturewidth = bloomtextureheight = 0;
8639
8640         // allocate textures as needed
8641         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8642         {
8643                 if (r_bloomstate.texture_screen)
8644                         R_FreeTexture(r_bloomstate.texture_screen);
8645                 r_bloomstate.texture_screen = NULL;
8646                 r_bloomstate.screentexturewidth = screentexturewidth;
8647                 r_bloomstate.screentextureheight = screentextureheight;
8648                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8649                         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);
8650         }
8651         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8652         {
8653                 if (r_bloomstate.texture_bloom)
8654                         R_FreeTexture(r_bloomstate.texture_bloom);
8655                 r_bloomstate.texture_bloom = NULL;
8656                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8657                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8658                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8659                         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);
8660         }
8661
8662         // when doing a reduced render (HDR) we want to use a smaller area
8663         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8664         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8665         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8666         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8667         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8668
8669         // set up a texcoord array for the full resolution screen image
8670         // (we have to keep this around to copy back during final render)
8671         r_bloomstate.screentexcoord2f[0] = 0;
8672         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8673         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8674         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8675         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8676         r_bloomstate.screentexcoord2f[5] = 0;
8677         r_bloomstate.screentexcoord2f[6] = 0;
8678         r_bloomstate.screentexcoord2f[7] = 0;
8679
8680         // set up a texcoord array for the reduced resolution bloom image
8681         // (which will be additive blended over the screen image)
8682         r_bloomstate.bloomtexcoord2f[0] = 0;
8683         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8684         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8685         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8686         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8687         r_bloomstate.bloomtexcoord2f[5] = 0;
8688         r_bloomstate.bloomtexcoord2f[6] = 0;
8689         r_bloomstate.bloomtexcoord2f[7] = 0;
8690
8691         switch(vid.renderpath)
8692         {
8693         case RENDERPATH_GL11:
8694         case RENDERPATH_GL13:
8695         case RENDERPATH_GL20:
8696         case RENDERPATH_CGGL:
8697                 break;
8698         case RENDERPATH_D3D9:
8699         case RENDERPATH_D3D10:
8700         case RENDERPATH_D3D11:
8701                 {
8702                         int i;
8703                         for (i = 0;i < 4;i++)
8704                         {
8705                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8706                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8707                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8708                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8709                         }
8710                 }
8711                 break;
8712         }
8713
8714         if (r_hdr.integer || r_bloom.integer)
8715         {
8716                 r_bloomstate.enabled = true;
8717                 r_bloomstate.hdr = r_hdr.integer != 0;
8718         }
8719
8720         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);
8721 }
8722
8723 void R_Bloom_CopyBloomTexture(float colorscale)
8724 {
8725         r_refdef.stats.bloom++;
8726
8727         // scale down screen texture to the bloom texture size
8728         CHECKGLERROR
8729         R_SetViewport(&r_bloomstate.viewport);
8730         GL_BlendFunc(GL_ONE, GL_ZERO);
8731         GL_Color(colorscale, colorscale, colorscale, 1);
8732         // 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...
8733         switch(vid.renderpath)
8734         {
8735         case RENDERPATH_GL11:
8736         case RENDERPATH_GL13:
8737         case RENDERPATH_GL20:
8738         case RENDERPATH_CGGL:
8739                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8740                 break;
8741         case RENDERPATH_D3D9:
8742         case RENDERPATH_D3D10:
8743         case RENDERPATH_D3D11:
8744                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8745                 break;
8746         }
8747         // TODO: do boxfilter scale-down in shader?
8748         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8749         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8750         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8751
8752         // we now have a bloom image in the framebuffer
8753         // copy it into the bloom image texture for later processing
8754         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);
8755         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8756 }
8757
8758 void R_Bloom_CopyHDRTexture(void)
8759 {
8760         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);
8761         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8762 }
8763
8764 void R_Bloom_MakeTexture(void)
8765 {
8766         int x, range, dir;
8767         float xoffset, yoffset, r, brighten;
8768
8769         r_refdef.stats.bloom++;
8770
8771         R_ResetViewRendering2D();
8772
8773         // we have a bloom image in the framebuffer
8774         CHECKGLERROR
8775         R_SetViewport(&r_bloomstate.viewport);
8776
8777         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8778         {
8779                 x *= 2;
8780                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8781                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8782                 GL_Color(r,r,r,1);
8783                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8784                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8785                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8786                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8787
8788                 // copy the vertically blurred bloom view to a texture
8789                 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);
8790                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8791         }
8792
8793         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8794         brighten = r_bloom_brighten.value;
8795         if (r_hdr.integer)
8796                 brighten *= r_hdr_range.value;
8797         brighten = sqrt(brighten);
8798         if(range >= 1)
8799                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8800         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8801
8802         for (dir = 0;dir < 2;dir++)
8803         {
8804                 // blend on at multiple vertical offsets to achieve a vertical blur
8805                 // TODO: do offset blends using GLSL
8806                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8807                 GL_BlendFunc(GL_ONE, GL_ZERO);
8808                 for (x = -range;x <= range;x++)
8809                 {
8810                         if (!dir){xoffset = 0;yoffset = x;}
8811                         else {xoffset = x;yoffset = 0;}
8812                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8813                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8814                         // compute a texcoord array with the specified x and y offset
8815                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8816                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8817                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8818                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8819                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8820                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8821                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8822                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8823                         // this r value looks like a 'dot' particle, fading sharply to
8824                         // black at the edges
8825                         // (probably not realistic but looks good enough)
8826                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8827                         //r = brighten/(range*2+1);
8828                         r = brighten / (range * 2 + 1);
8829                         if(range >= 1)
8830                                 r *= (1 - x*x/(float)(range*range));
8831                         GL_Color(r, r, r, 1);
8832                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8833                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8834                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8835                         GL_BlendFunc(GL_ONE, GL_ONE);
8836                 }
8837
8838                 // copy the vertically blurred bloom view to a texture
8839                 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);
8840                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8841         }
8842 }
8843
8844 void R_HDR_RenderBloomTexture(void)
8845 {
8846         int oldwidth, oldheight;
8847         float oldcolorscale;
8848
8849         oldcolorscale = r_refdef.view.colorscale;
8850         oldwidth = r_refdef.view.width;
8851         oldheight = r_refdef.view.height;
8852         r_refdef.view.width = r_bloomstate.bloomwidth;
8853         r_refdef.view.height = r_bloomstate.bloomheight;
8854
8855         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8856         // TODO: add exposure compensation features
8857         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8858
8859         r_refdef.view.showdebug = false;
8860         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8861
8862         R_ResetViewRendering3D();
8863
8864         R_ClearScreen(r_refdef.fogenabled);
8865         if (r_timereport_active)
8866                 R_TimeReport("HDRclear");
8867
8868         R_View_Update();
8869         if (r_timereport_active)
8870                 R_TimeReport("visibility");
8871
8872         // only do secondary renders with HDR if r_hdr is 2 or higher
8873         r_waterstate.numwaterplanes = 0;
8874         if (r_waterstate.enabled && r_hdr.integer >= 2)
8875                 R_RenderWaterPlanes();
8876
8877         r_refdef.view.showdebug = true;
8878         R_RenderScene();
8879         r_waterstate.numwaterplanes = 0;
8880
8881         R_ResetViewRendering2D();
8882
8883         R_Bloom_CopyHDRTexture();
8884         R_Bloom_MakeTexture();
8885
8886         // restore the view settings
8887         r_refdef.view.width = oldwidth;
8888         r_refdef.view.height = oldheight;
8889         r_refdef.view.colorscale = oldcolorscale;
8890
8891         R_ResetViewRendering3D();
8892
8893         R_ClearScreen(r_refdef.fogenabled);
8894         if (r_timereport_active)
8895                 R_TimeReport("viewclear");
8896 }
8897
8898 static void R_BlendView(void)
8899 {
8900         unsigned int permutation;
8901         float uservecs[4][4];
8902
8903         switch (vid.renderpath)
8904         {
8905         case RENDERPATH_GL20:
8906         case RENDERPATH_CGGL:
8907         case RENDERPATH_D3D9:
8908         case RENDERPATH_D3D10:
8909         case RENDERPATH_D3D11:
8910                 permutation =
8911                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8912                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8913                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8914                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8915                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8916
8917                 if (r_bloomstate.texture_screen)
8918                 {
8919                         // make sure the buffer is available
8920                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8921
8922                         R_ResetViewRendering2D();
8923
8924                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8925                         {
8926                                 // declare variables
8927                                 float speed;
8928                                 static float avgspeed;
8929
8930                                 speed = VectorLength(cl.movement_velocity);
8931
8932                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8933                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8934
8935                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8936                                 speed = bound(0, speed, 1);
8937                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8938
8939                                 // calculate values into a standard alpha
8940                                 cl.motionbluralpha = 1 - exp(-
8941                                                 (
8942                                                  (r_motionblur.value * speed / 80)
8943                                                  +
8944                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8945                                                 )
8946                                                 /
8947                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8948                                            );
8949
8950                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8951                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8952                                 // apply the blur
8953                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8954                                 {
8955                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8956                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8957                                         switch(vid.renderpath)
8958                                         {
8959                                         case RENDERPATH_GL11:
8960                                         case RENDERPATH_GL13:
8961                                         case RENDERPATH_GL20:
8962                                         case RENDERPATH_CGGL:
8963                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8964                                                 break;
8965                                         case RENDERPATH_D3D9:
8966                                         case RENDERPATH_D3D10:
8967                                         case RENDERPATH_D3D11:
8968                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8969                                                 break;
8970                                         }
8971                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8972                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8973                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8974                                 }
8975                         }
8976
8977                         // copy view into the screen texture
8978                         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);
8979                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8980                 }
8981                 else if (!r_bloomstate.texture_bloom)
8982                 {
8983                         // we may still have to do view tint...
8984                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8985                         {
8986                                 // apply a color tint to the whole view
8987                                 R_ResetViewRendering2D();
8988                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8989                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8990                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8991                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8992                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8993                         }
8994                         break; // no screen processing, no bloom, skip it
8995                 }
8996
8997                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8998                 {
8999                         // render simple bloom effect
9000                         // copy the screen and shrink it and darken it for the bloom process
9001                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9002                         // make the bloom texture
9003                         R_Bloom_MakeTexture();
9004                 }
9005
9006 #if _MSC_VER >= 1400
9007 #define sscanf sscanf_s
9008 #endif
9009                 memset(uservecs, 0, sizeof(uservecs));
9010                 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9011                 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9012                 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9013                 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9014
9015                 R_ResetViewRendering2D();
9016                 GL_Color(1, 1, 1, 1);
9017                 GL_BlendFunc(GL_ONE, GL_ZERO);
9018
9019                 switch(vid.renderpath)
9020                 {
9021                 case RENDERPATH_GL20:
9022                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9023                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9024                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9025                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9026                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9027                         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]);
9028                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9029                         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]);
9030                         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]);
9031                         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]);
9032                         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]);
9033                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9034                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9035                         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);
9036                         break;
9037                 case RENDERPATH_CGGL:
9038 #ifdef SUPPORTCG
9039                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9040                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9041                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9042                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9043                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9044                         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
9045                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9046                         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
9047                         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
9048                         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
9049                         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
9050                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9051                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9052                         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);
9053 #endif
9054                         break;
9055                 case RENDERPATH_D3D9:
9056 #ifdef SUPPORTD3D
9057                         // 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...
9058                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9059                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9060                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9061                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9062                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9063                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9064                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9065                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9066                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9067                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9068                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9069                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9070                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9071                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9072 #endif
9073                         break;
9074                 case RENDERPATH_D3D10:
9075                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9076                         break;
9077                 case RENDERPATH_D3D11:
9078                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9079                         break;
9080                 default:
9081                         break;
9082                 }
9083                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9084                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9085                 break;
9086         case RENDERPATH_GL13:
9087         case RENDERPATH_GL11:
9088                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9089                 {
9090                         // apply a color tint to the whole view
9091                         R_ResetViewRendering2D();
9092                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9093                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9094                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9095                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9096                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9097                 }
9098                 break;
9099         }
9100 }
9101
9102 matrix4x4_t r_waterscrollmatrix;
9103
9104 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9105 {
9106         if (r_refdef.fog_density)
9107         {
9108                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9109                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9110                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9111
9112                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9113                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9114                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9115                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9116
9117                 {
9118                         vec3_t fogvec;
9119                         VectorCopy(r_refdef.fogcolor, fogvec);
9120                         //   color.rgb *= ContrastBoost * SceneBrightness;
9121                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9122                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9123                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9124                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9125                 }
9126         }
9127 }
9128
9129 void R_UpdateVariables(void)
9130 {
9131         R_Textures_Frame();
9132
9133         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9134
9135         r_refdef.farclip = r_farclip_base.value;
9136         if (r_refdef.scene.worldmodel)
9137                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9138         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9139
9140         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9141                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9142         r_refdef.polygonfactor = 0;
9143         r_refdef.polygonoffset = 0;
9144         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9145         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9146
9147         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9148         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9149         r_refdef.scene.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
9150         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9151         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9152         if (r_showsurfaces.integer)
9153         {
9154                 r_refdef.scene.rtworld = false;
9155                 r_refdef.scene.rtworldshadows = false;
9156                 r_refdef.scene.rtdlight = false;
9157                 r_refdef.scene.rtdlightshadows = false;
9158                 r_refdef.lightmapintensity = 0;
9159         }
9160
9161         if (gamemode == GAME_NEHAHRA)
9162         {
9163                 if (gl_fogenable.integer)
9164                 {
9165                         r_refdef.oldgl_fogenable = true;
9166                         r_refdef.fog_density = gl_fogdensity.value;
9167                         r_refdef.fog_red = gl_fogred.value;
9168                         r_refdef.fog_green = gl_foggreen.value;
9169                         r_refdef.fog_blue = gl_fogblue.value;
9170                         r_refdef.fog_alpha = 1;
9171                         r_refdef.fog_start = 0;
9172                         r_refdef.fog_end = gl_skyclip.value;
9173                         r_refdef.fog_height = 1<<30;
9174                         r_refdef.fog_fadedepth = 128;
9175                 }
9176                 else if (r_refdef.oldgl_fogenable)
9177                 {
9178                         r_refdef.oldgl_fogenable = false;
9179                         r_refdef.fog_density = 0;
9180                         r_refdef.fog_red = 0;
9181                         r_refdef.fog_green = 0;
9182                         r_refdef.fog_blue = 0;
9183                         r_refdef.fog_alpha = 0;
9184                         r_refdef.fog_start = 0;
9185                         r_refdef.fog_end = 0;
9186                         r_refdef.fog_height = 1<<30;
9187                         r_refdef.fog_fadedepth = 128;
9188                 }
9189         }
9190
9191         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9192         r_refdef.fog_start = max(0, r_refdef.fog_start);
9193         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9194
9195         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9196
9197         if (r_refdef.fog_density && r_drawfog.integer)
9198         {
9199                 r_refdef.fogenabled = true;
9200                 // this is the point where the fog reaches 0.9986 alpha, which we
9201                 // consider a good enough cutoff point for the texture
9202                 // (0.9986 * 256 == 255.6)
9203                 if (r_fog_exp2.integer)
9204                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9205                 else
9206                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9207                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9208                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9209                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9210                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9211                         R_BuildFogHeightTexture();
9212                 // fog color was already set
9213                 // update the fog texture
9214                 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)
9215                         R_BuildFogTexture();
9216                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9217                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9218         }
9219         else
9220                 r_refdef.fogenabled = false;
9221
9222         switch(vid.renderpath)
9223         {
9224         case RENDERPATH_GL20:
9225         case RENDERPATH_CGGL:
9226         case RENDERPATH_D3D9:
9227         case RENDERPATH_D3D10:
9228         case RENDERPATH_D3D11:
9229                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9230                 {
9231                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9232                         {
9233                                 // build GLSL gamma texture
9234 #define RAMPWIDTH 256
9235                                 unsigned short ramp[RAMPWIDTH * 3];
9236                                 unsigned char rampbgr[RAMPWIDTH][4];
9237                                 int i;
9238
9239                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9240
9241                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9242                                 for(i = 0; i < RAMPWIDTH; ++i)
9243                                 {
9244                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9245                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9246                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9247                                         rampbgr[i][3] = 0;
9248                                 }
9249                                 if (r_texture_gammaramps)
9250                                 {
9251                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9252                                 }
9253                                 else
9254                                 {
9255                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9256                                 }
9257                         }
9258                 }
9259                 else
9260                 {
9261                         // remove GLSL gamma texture
9262                 }
9263                 break;
9264         case RENDERPATH_GL13:
9265         case RENDERPATH_GL11:
9266                 break;
9267         }
9268 }
9269
9270 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9271 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9272 /*
9273 ================
9274 R_SelectScene
9275 ================
9276 */
9277 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9278         if( scenetype != r_currentscenetype ) {
9279                 // store the old scenetype
9280                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9281                 r_currentscenetype = scenetype;
9282                 // move in the new scene
9283                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9284         }
9285 }
9286
9287 /*
9288 ================
9289 R_GetScenePointer
9290 ================
9291 */
9292 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9293 {
9294         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9295         if( scenetype == r_currentscenetype ) {
9296                 return &r_refdef.scene;
9297         } else {
9298                 return &r_scenes_store[ scenetype ];
9299         }
9300 }
9301
9302 /*
9303 ================
9304 R_RenderView
9305 ================
9306 */
9307 void R_RenderView(void)
9308 {
9309         if (r_timereport_active)
9310                 R_TimeReport("start");
9311         r_textureframe++; // used only by R_GetCurrentTexture
9312         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9313
9314         if (!r_drawentities.integer)
9315                 r_refdef.scene.numentities = 0;
9316
9317         R_AnimCache_ClearCache();
9318         R_FrameData_NewFrame();
9319
9320         if (r_refdef.view.isoverlay)
9321         {
9322                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9323                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9324                 R_TimeReport("depthclear");
9325
9326                 r_refdef.view.showdebug = false;
9327
9328                 r_waterstate.enabled = false;
9329                 r_waterstate.numwaterplanes = 0;
9330
9331                 R_RenderScene();
9332
9333                 CHECKGLERROR
9334                 return;
9335         }
9336
9337         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9338                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9339
9340         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9341
9342         R_RenderView_UpdateViewVectors();
9343
9344         R_Shadow_UpdateWorldLightSelection();
9345
9346         R_Bloom_StartFrame();
9347         R_Water_StartFrame();
9348
9349         CHECKGLERROR
9350         if (r_timereport_active)
9351                 R_TimeReport("viewsetup");
9352
9353         R_ResetViewRendering3D();
9354
9355         if (r_refdef.view.clear || r_refdef.fogenabled)
9356         {
9357                 R_ClearScreen(r_refdef.fogenabled);
9358                 if (r_timereport_active)
9359                         R_TimeReport("viewclear");
9360         }
9361         r_refdef.view.clear = true;
9362
9363         // this produces a bloom texture to be used in R_BlendView() later
9364         if (r_hdr.integer && r_bloomstate.bloomwidth)
9365         {
9366                 R_HDR_RenderBloomTexture();
9367                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9368                 r_textureframe++; // used only by R_GetCurrentTexture
9369         }
9370
9371         r_refdef.view.showdebug = true;
9372
9373         R_View_Update();
9374         if (r_timereport_active)
9375                 R_TimeReport("visibility");
9376
9377         r_waterstate.numwaterplanes = 0;
9378         if (r_waterstate.enabled)
9379                 R_RenderWaterPlanes();
9380
9381         R_RenderScene();
9382         r_waterstate.numwaterplanes = 0;
9383
9384         R_BlendView();
9385         if (r_timereport_active)
9386                 R_TimeReport("blendview");
9387
9388         GL_Scissor(0, 0, vid.width, vid.height);
9389         GL_ScissorTest(false);
9390         CHECKGLERROR
9391 }
9392
9393 void R_RenderWaterPlanes(void)
9394 {
9395         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9396         {
9397                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9398                 if (r_timereport_active)
9399                         R_TimeReport("waterworld");
9400         }
9401
9402         // don't let sound skip if going slow
9403         if (r_refdef.scene.extraupdate)
9404                 S_ExtraUpdate ();
9405
9406         R_DrawModelsAddWaterPlanes();
9407         if (r_timereport_active)
9408                 R_TimeReport("watermodels");
9409
9410         if (r_waterstate.numwaterplanes)
9411         {
9412                 R_Water_ProcessPlanes();
9413                 if (r_timereport_active)
9414                         R_TimeReport("waterscenes");
9415         }
9416 }
9417
9418 extern void R_DrawLightningBeams (void);
9419 extern void VM_CL_AddPolygonsToMeshQueue (void);
9420 extern void R_DrawPortals (void);
9421 extern cvar_t cl_locs_show;
9422 static void R_DrawLocs(void);
9423 static void R_DrawEntityBBoxes(void);
9424 static void R_DrawModelDecals(void);
9425 extern void R_DrawModelShadows(void);
9426 extern void R_DrawModelShadowMaps(void);
9427 extern cvar_t cl_decals_newsystem;
9428 extern qboolean r_shadow_usingdeferredprepass;
9429 void R_RenderScene(void)
9430 {
9431         qboolean shadowmapping = false;
9432
9433         if (r_timereport_active)
9434                 R_TimeReport("beginscene");
9435
9436         r_refdef.stats.renders++;
9437
9438         R_UpdateFogColor();
9439
9440         // don't let sound skip if going slow
9441         if (r_refdef.scene.extraupdate)
9442                 S_ExtraUpdate ();
9443
9444         R_MeshQueue_BeginScene();
9445
9446         R_SkyStartFrame();
9447
9448         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);
9449
9450         if (r_timereport_active)
9451                 R_TimeReport("skystartframe");
9452
9453         if (cl.csqc_vidvars.drawworld)
9454         {
9455                 // don't let sound skip if going slow
9456                 if (r_refdef.scene.extraupdate)
9457                         S_ExtraUpdate ();
9458
9459                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9460                 {
9461                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9462                         if (r_timereport_active)
9463                                 R_TimeReport("worldsky");
9464                 }
9465
9466                 if (R_DrawBrushModelsSky() && r_timereport_active)
9467                         R_TimeReport("bmodelsky");
9468
9469                 if (skyrendermasked && skyrenderlater)
9470                 {
9471                         // we have to force off the water clipping plane while rendering sky
9472                         R_SetupView(false);
9473                         R_Sky();
9474                         R_SetupView(true);
9475                         if (r_timereport_active)
9476                                 R_TimeReport("sky");
9477                 }
9478         }
9479
9480         R_AnimCache_CacheVisibleEntities();
9481         if (r_timereport_active)
9482                 R_TimeReport("animation");
9483
9484         R_Shadow_PrepareLights();
9485         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9486                 R_Shadow_PrepareModelShadows();
9487         if (r_timereport_active)
9488                 R_TimeReport("preparelights");
9489
9490         if (R_Shadow_ShadowMappingEnabled())
9491                 shadowmapping = true;
9492
9493         if (r_shadow_usingdeferredprepass)
9494                 R_Shadow_DrawPrepass();
9495
9496         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9497         {
9498                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9499                 if (r_timereport_active)
9500                         R_TimeReport("worlddepth");
9501         }
9502         if (r_depthfirst.integer >= 2)
9503         {
9504                 R_DrawModelsDepth();
9505                 if (r_timereport_active)
9506                         R_TimeReport("modeldepth");
9507         }
9508
9509         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9510         {
9511                 R_DrawModelShadowMaps();
9512                 R_ResetViewRendering3D();
9513                 // don't let sound skip if going slow
9514                 if (r_refdef.scene.extraupdate)
9515                         S_ExtraUpdate ();
9516         }
9517
9518         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9519         {
9520                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9521                 if (r_timereport_active)
9522                         R_TimeReport("world");
9523         }
9524
9525         // don't let sound skip if going slow
9526         if (r_refdef.scene.extraupdate)
9527                 S_ExtraUpdate ();
9528
9529         R_DrawModels();
9530         if (r_timereport_active)
9531                 R_TimeReport("models");
9532
9533         // don't let sound skip if going slow
9534         if (r_refdef.scene.extraupdate)
9535                 S_ExtraUpdate ();
9536
9537         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9538         {
9539                 R_DrawModelShadows();
9540                 R_ResetViewRendering3D();
9541                 // don't let sound skip if going slow
9542                 if (r_refdef.scene.extraupdate)
9543                         S_ExtraUpdate ();
9544         }
9545
9546         if (!r_shadow_usingdeferredprepass)
9547         {
9548                 R_Shadow_DrawLights();
9549                 if (r_timereport_active)
9550                         R_TimeReport("rtlights");
9551         }
9552
9553         // don't let sound skip if going slow
9554         if (r_refdef.scene.extraupdate)
9555                 S_ExtraUpdate ();
9556
9557         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9558         {
9559                 R_DrawModelShadows();
9560                 R_ResetViewRendering3D();
9561                 // don't let sound skip if going slow
9562                 if (r_refdef.scene.extraupdate)
9563                         S_ExtraUpdate ();
9564         }
9565
9566         if (cl.csqc_vidvars.drawworld)
9567         {
9568                 if (cl_decals_newsystem.integer)
9569                 {
9570                         R_DrawModelDecals();
9571                         if (r_timereport_active)
9572                                 R_TimeReport("modeldecals");
9573                 }
9574                 else
9575                 {
9576                         R_DrawDecals();
9577                         if (r_timereport_active)
9578                                 R_TimeReport("decals");
9579                 }
9580
9581                 R_DrawParticles();
9582                 if (r_timereport_active)
9583                         R_TimeReport("particles");
9584
9585                 R_DrawExplosions();
9586                 if (r_timereport_active)
9587                         R_TimeReport("explosions");
9588
9589                 R_DrawLightningBeams();
9590                 if (r_timereport_active)
9591                         R_TimeReport("lightning");
9592         }
9593
9594         VM_CL_AddPolygonsToMeshQueue();
9595
9596         if (r_refdef.view.showdebug)
9597         {
9598                 if (cl_locs_show.integer)
9599                 {
9600                         R_DrawLocs();
9601                         if (r_timereport_active)
9602                                 R_TimeReport("showlocs");
9603                 }
9604
9605                 if (r_drawportals.integer)
9606                 {
9607                         R_DrawPortals();
9608                         if (r_timereport_active)
9609                                 R_TimeReport("portals");
9610                 }
9611
9612                 if (r_showbboxes.value > 0)
9613                 {
9614                         R_DrawEntityBBoxes();
9615                         if (r_timereport_active)
9616                                 R_TimeReport("bboxes");
9617                 }
9618         }
9619
9620         R_MeshQueue_RenderTransparent();
9621         if (r_timereport_active)
9622                 R_TimeReport("drawtrans");
9623
9624         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))
9625         {
9626                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9627                 if (r_timereport_active)
9628                         R_TimeReport("worlddebug");
9629                 R_DrawModelsDebug();
9630                 if (r_timereport_active)
9631                         R_TimeReport("modeldebug");
9632         }
9633
9634         if (cl.csqc_vidvars.drawworld)
9635         {
9636                 R_Shadow_DrawCoronas();
9637                 if (r_timereport_active)
9638                         R_TimeReport("coronas");
9639         }
9640
9641         // don't let sound skip if going slow
9642         if (r_refdef.scene.extraupdate)
9643                 S_ExtraUpdate ();
9644
9645         R_ResetViewRendering2D();
9646 }
9647
9648 static const unsigned short bboxelements[36] =
9649 {
9650         5, 1, 3, 5, 3, 7,
9651         6, 2, 0, 6, 0, 4,
9652         7, 3, 2, 7, 2, 6,
9653         4, 0, 1, 4, 1, 5,
9654         4, 5, 7, 4, 7, 6,
9655         1, 0, 2, 1, 2, 3,
9656 };
9657
9658 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9659 {
9660         int i;
9661         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9662
9663         RSurf_ActiveWorldEntity();
9664
9665         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9666         GL_DepthMask(false);
9667         GL_DepthRange(0, 1);
9668         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9669         R_Mesh_ResetTextureState();
9670
9671         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9672         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9673         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9674         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9675         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9676         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9677         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9678         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9679         R_FillColors(color4f, 8, cr, cg, cb, ca);
9680         if (r_refdef.fogenabled)
9681         {
9682                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9683                 {
9684                         f1 = RSurf_FogVertex(v);
9685                         f2 = 1 - f1;
9686                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9687                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9688                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9689                 }
9690         }
9691         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9692         R_Mesh_ResetTextureState();
9693         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9694         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9695 }
9696
9697 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9698 {
9699         int i;
9700         float color[4];
9701         prvm_edict_t *edict;
9702         prvm_prog_t *prog_save = prog;
9703
9704         // this function draws bounding boxes of server entities
9705         if (!sv.active)
9706                 return;
9707
9708         GL_CullFace(GL_NONE);
9709         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9710
9711         prog = 0;
9712         SV_VM_Begin();
9713         for (i = 0;i < numsurfaces;i++)
9714         {
9715                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9716                 switch ((int)edict->fields.server->solid)
9717                 {
9718                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9719                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9720                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9721                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9722                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9723                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9724                 }
9725                 color[3] *= r_showbboxes.value;
9726                 color[3] = bound(0, color[3], 1);
9727                 GL_DepthTest(!r_showdisabledepthtest.integer);
9728                 GL_CullFace(r_refdef.view.cullface_front);
9729                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9730         }
9731         SV_VM_End();
9732         prog = prog_save;
9733 }
9734
9735 static void R_DrawEntityBBoxes(void)
9736 {
9737         int i;
9738         prvm_edict_t *edict;
9739         vec3_t center;
9740         prvm_prog_t *prog_save = prog;
9741
9742         // this function draws bounding boxes of server entities
9743         if (!sv.active)
9744                 return;
9745
9746         prog = 0;
9747         SV_VM_Begin();
9748         for (i = 0;i < prog->num_edicts;i++)
9749         {
9750                 edict = PRVM_EDICT_NUM(i);
9751                 if (edict->priv.server->free)
9752                         continue;
9753                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9754                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9755                         continue;
9756                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9757                         continue;
9758                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9759                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9760         }
9761         SV_VM_End();
9762         prog = prog_save;
9763 }
9764
9765 static const int nomodelelement3i[24] =
9766 {
9767         5, 2, 0,
9768         5, 1, 2,
9769         5, 0, 3,
9770         5, 3, 1,
9771         0, 2, 4,
9772         2, 1, 4,
9773         3, 0, 4,
9774         1, 3, 4
9775 };
9776
9777 static const unsigned short nomodelelement3s[24] =
9778 {
9779         5, 2, 0,
9780         5, 1, 2,
9781         5, 0, 3,
9782         5, 3, 1,
9783         0, 2, 4,
9784         2, 1, 4,
9785         3, 0, 4,
9786         1, 3, 4
9787 };
9788
9789 static const float nomodelvertex3f[6*3] =
9790 {
9791         -16,   0,   0,
9792          16,   0,   0,
9793           0, -16,   0,
9794           0,  16,   0,
9795           0,   0, -16,
9796           0,   0,  16
9797 };
9798
9799 static const float nomodelcolor4f[6*4] =
9800 {
9801         0.0f, 0.0f, 0.5f, 1.0f,
9802         0.0f, 0.0f, 0.5f, 1.0f,
9803         0.0f, 0.5f, 0.0f, 1.0f,
9804         0.0f, 0.5f, 0.0f, 1.0f,
9805         0.5f, 0.0f, 0.0f, 1.0f,
9806         0.5f, 0.0f, 0.0f, 1.0f
9807 };
9808
9809 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9810 {
9811         int i;
9812         float f1, f2, *c;
9813         float color4f[6*4];
9814
9815         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);
9816
9817         // this is only called once per entity so numsurfaces is always 1, and
9818         // surfacelist is always {0}, so this code does not handle batches
9819
9820         if (rsurface.ent_flags & RENDER_ADDITIVE)
9821         {
9822                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9823                 GL_DepthMask(false);
9824         }
9825         else if (rsurface.colormod[3] < 1)
9826         {
9827                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9828                 GL_DepthMask(false);
9829         }
9830         else
9831         {
9832                 GL_BlendFunc(GL_ONE, GL_ZERO);
9833                 GL_DepthMask(true);
9834         }
9835         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9836         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9837         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9838         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9839         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9840         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9841         for (i = 0, c = color4f;i < 6;i++, c += 4)
9842         {
9843                 c[0] *= rsurface.colormod[0];
9844                 c[1] *= rsurface.colormod[1];
9845                 c[2] *= rsurface.colormod[2];
9846                 c[3] *= rsurface.colormod[3];
9847         }
9848         if (r_refdef.fogenabled)
9849         {
9850                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9851                 {
9852                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9853                         f2 = 1 - f1;
9854                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9855                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9856                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9857                 }
9858         }
9859         R_Mesh_ResetTextureState();
9860         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9861         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9862 }
9863
9864 void R_DrawNoModel(entity_render_t *ent)
9865 {
9866         vec3_t org;
9867         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9868         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9869                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9870         else
9871                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9872 }
9873
9874 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9875 {
9876         vec3_t right1, right2, diff, normal;
9877
9878         VectorSubtract (org2, org1, normal);
9879
9880         // calculate 'right' vector for start
9881         VectorSubtract (r_refdef.view.origin, org1, diff);
9882         CrossProduct (normal, diff, right1);
9883         VectorNormalize (right1);
9884
9885         // calculate 'right' vector for end
9886         VectorSubtract (r_refdef.view.origin, org2, diff);
9887         CrossProduct (normal, diff, right2);
9888         VectorNormalize (right2);
9889
9890         vert[ 0] = org1[0] + width * right1[0];
9891         vert[ 1] = org1[1] + width * right1[1];
9892         vert[ 2] = org1[2] + width * right1[2];
9893         vert[ 3] = org1[0] - width * right1[0];
9894         vert[ 4] = org1[1] - width * right1[1];
9895         vert[ 5] = org1[2] - width * right1[2];
9896         vert[ 6] = org2[0] - width * right2[0];
9897         vert[ 7] = org2[1] - width * right2[1];
9898         vert[ 8] = org2[2] - width * right2[2];
9899         vert[ 9] = org2[0] + width * right2[0];
9900         vert[10] = org2[1] + width * right2[1];
9901         vert[11] = org2[2] + width * right2[2];
9902 }
9903
9904 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)
9905 {
9906         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9907         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9908         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9909         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9910         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9911         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9912         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9913         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9914         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9915         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9916         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9917         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9918 }
9919
9920 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9921 {
9922         int i;
9923         float *vertex3f;
9924         float v[3];
9925         VectorSet(v, x, y, z);
9926         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9927                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9928                         break;
9929         if (i == mesh->numvertices)
9930         {
9931                 if (mesh->numvertices < mesh->maxvertices)
9932                 {
9933                         VectorCopy(v, vertex3f);
9934                         mesh->numvertices++;
9935                 }
9936                 return mesh->numvertices;
9937         }
9938         else
9939                 return i;
9940 }
9941
9942 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9943 {
9944         int i;
9945         int *e, element[3];
9946         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9947         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9948         e = mesh->element3i + mesh->numtriangles * 3;
9949         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9950         {
9951                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9952                 if (mesh->numtriangles < mesh->maxtriangles)
9953                 {
9954                         *e++ = element[0];
9955                         *e++ = element[1];
9956                         *e++ = element[2];
9957                         mesh->numtriangles++;
9958                 }
9959                 element[1] = element[2];
9960         }
9961 }
9962
9963 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9964 {
9965         int i;
9966         int *e, element[3];
9967         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9968         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9969         e = mesh->element3i + mesh->numtriangles * 3;
9970         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9971         {
9972                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9973                 if (mesh->numtriangles < mesh->maxtriangles)
9974                 {
9975                         *e++ = element[0];
9976                         *e++ = element[1];
9977                         *e++ = element[2];
9978                         mesh->numtriangles++;
9979                 }
9980                 element[1] = element[2];
9981         }
9982 }
9983
9984 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9985 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9986 {
9987         int planenum, planenum2;
9988         int w;
9989         int tempnumpoints;
9990         mplane_t *plane, *plane2;
9991         double maxdist;
9992         double temppoints[2][256*3];
9993         // figure out how large a bounding box we need to properly compute this brush
9994         maxdist = 0;
9995         for (w = 0;w < numplanes;w++)
9996                 maxdist = max(maxdist, fabs(planes[w].dist));
9997         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9998         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9999         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10000         {
10001                 w = 0;
10002                 tempnumpoints = 4;
10003                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10004                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10005                 {
10006                         if (planenum2 == planenum)
10007                                 continue;
10008                         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);
10009                         w = !w;
10010                 }
10011                 if (tempnumpoints < 3)
10012                         continue;
10013                 // generate elements forming a triangle fan for this polygon
10014                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10015         }
10016 }
10017
10018 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)
10019 {
10020         texturelayer_t *layer;
10021         layer = t->currentlayers + t->currentnumlayers++;
10022         layer->type = type;
10023         layer->depthmask = depthmask;
10024         layer->blendfunc1 = blendfunc1;
10025         layer->blendfunc2 = blendfunc2;
10026         layer->texture = texture;
10027         layer->texmatrix = *matrix;
10028         layer->color[0] = r;
10029         layer->color[1] = g;
10030         layer->color[2] = b;
10031         layer->color[3] = a;
10032 }
10033
10034 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10035 {
10036         if(parms[0] == 0 && parms[1] == 0)
10037                 return false;
10038         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10039                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10040                         return false;
10041         return true;
10042 }
10043
10044 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10045 {
10046         double index, f;
10047         index = parms[2] + r_refdef.scene.time * parms[3];
10048         index -= floor(index);
10049         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10050         {
10051         default:
10052         case Q3WAVEFUNC_NONE:
10053         case Q3WAVEFUNC_NOISE:
10054         case Q3WAVEFUNC_COUNT:
10055                 f = 0;
10056                 break;
10057         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10058         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10059         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10060         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10061         case Q3WAVEFUNC_TRIANGLE:
10062                 index *= 4;
10063                 f = index - floor(index);
10064                 if (index < 1)
10065                         f = f;
10066                 else if (index < 2)
10067                         f = 1 - f;
10068                 else if (index < 3)
10069                         f = -f;
10070                 else
10071                         f = -(1 - f);
10072                 break;
10073         }
10074         f = parms[0] + parms[1] * f;
10075         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10076                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10077         return (float) f;
10078 }
10079
10080 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10081 {
10082         int w, h, idx;
10083         float f;
10084         float tcmat[12];
10085         matrix4x4_t matrix, temp;
10086         switch(tcmod->tcmod)
10087         {
10088                 case Q3TCMOD_COUNT:
10089                 case Q3TCMOD_NONE:
10090                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10091                                 matrix = r_waterscrollmatrix;
10092                         else
10093                                 matrix = identitymatrix;
10094                         break;
10095                 case Q3TCMOD_ENTITYTRANSLATE:
10096                         // this is used in Q3 to allow the gamecode to control texcoord
10097                         // scrolling on the entity, which is not supported in darkplaces yet.
10098                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10099                         break;
10100                 case Q3TCMOD_ROTATE:
10101                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10102                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10103                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10104                         break;
10105                 case Q3TCMOD_SCALE:
10106                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10107                         break;
10108                 case Q3TCMOD_SCROLL:
10109                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10110                         break;
10111                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10112                         w = (int) tcmod->parms[0];
10113                         h = (int) tcmod->parms[1];
10114                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10115                         f = f - floor(f);
10116                         idx = (int) floor(f * w * h);
10117                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10118                         break;
10119                 case Q3TCMOD_STRETCH:
10120                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10121                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10122                         break;
10123                 case Q3TCMOD_TRANSFORM:
10124                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10125                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10126                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10127                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10128                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10129                         break;
10130                 case Q3TCMOD_TURBULENT:
10131                         // this is handled in the RSurf_PrepareVertices function
10132                         matrix = identitymatrix;
10133                         break;
10134         }
10135         temp = *texmatrix;
10136         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10137 }
10138
10139 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10140 {
10141         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10142         char name[MAX_QPATH];
10143         skinframe_t *skinframe;
10144         unsigned char pixels[296*194];
10145         strlcpy(cache->name, skinname, sizeof(cache->name));
10146         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10147         if (developer_loading.integer)
10148                 Con_Printf("loading %s\n", name);
10149         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10150         if (!skinframe || !skinframe->base)
10151         {
10152                 unsigned char *f;
10153                 fs_offset_t filesize;
10154                 skinframe = NULL;
10155                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10156                 if (f)
10157                 {
10158                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10159                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10160                         Mem_Free(f);
10161                 }
10162         }
10163         cache->skinframe = skinframe;
10164 }
10165
10166 texture_t *R_GetCurrentTexture(texture_t *t)
10167 {
10168         int i;
10169         const entity_render_t *ent = rsurface.entity;
10170         dp_model_t *model = ent->model;
10171         q3shaderinfo_layer_tcmod_t *tcmod;
10172
10173         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10174                 return t->currentframe;
10175         t->update_lastrenderframe = r_textureframe;
10176         t->update_lastrenderentity = (void *)ent;
10177
10178         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10179                 t->camera_entity = ent->entitynumber;
10180         else
10181                 t->camera_entity = 0;
10182
10183         // switch to an alternate material if this is a q1bsp animated material
10184         {
10185                 texture_t *texture = t;
10186                 int s = rsurface.ent_skinnum;
10187                 if ((unsigned int)s >= (unsigned int)model->numskins)
10188                         s = 0;
10189                 if (model->skinscenes)
10190                 {
10191                         if (model->skinscenes[s].framecount > 1)
10192                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10193                         else
10194                                 s = model->skinscenes[s].firstframe;
10195                 }
10196                 if (s > 0)
10197                         t = t + s * model->num_surfaces;
10198                 if (t->animated)
10199                 {
10200                         // use an alternate animation if the entity's frame is not 0,
10201                         // and only if the texture has an alternate animation
10202                         if (rsurface.ent_alttextures && t->anim_total[1])
10203                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10204                         else
10205                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10206                 }
10207                 texture->currentframe = t;
10208         }
10209
10210         // update currentskinframe to be a qw skin or animation frame
10211         if (rsurface.ent_qwskin >= 0)
10212         {
10213                 i = rsurface.ent_qwskin;
10214                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10215                 {
10216                         r_qwskincache_size = cl.maxclients;
10217                         if (r_qwskincache)
10218                                 Mem_Free(r_qwskincache);
10219                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10220                 }
10221                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10222                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10223                 t->currentskinframe = r_qwskincache[i].skinframe;
10224                 if (t->currentskinframe == NULL)
10225                         t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10226         }
10227         else if (t->numskinframes >= 2)
10228                 t->currentskinframe = t->skinframes[(int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10229         if (t->backgroundnumskinframes >= 2)
10230                 t->backgroundcurrentskinframe = t->backgroundskinframes[(int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10231
10232         t->currentmaterialflags = t->basematerialflags;
10233         t->currentalpha = rsurface.colormod[3];
10234         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10235                 t->currentalpha *= r_wateralpha.value;
10236         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10237                 t->currentalpha *= t->r_water_wateralpha;
10238         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10239                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10240         if (!(rsurface.ent_flags & RENDER_LIGHT))
10241                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10242         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10243         {
10244                 // pick a model lighting mode
10245                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10246                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10247                 else
10248                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10249         }
10250         if (rsurface.ent_flags & RENDER_ADDITIVE)
10251                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10252         else if (t->currentalpha < 1)
10253                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10254         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10255                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10256         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10257                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10258         if (t->backgroundnumskinframes)
10259                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10260         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10261         {
10262                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10263                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10264         }
10265         else
10266                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10267         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10268                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10269
10270         // there is no tcmod
10271         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10272         {
10273                 t->currenttexmatrix = r_waterscrollmatrix;
10274                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10275         }
10276         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10277         {
10278                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10279                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10280         }
10281
10282         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10283                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10284         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10285                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10286
10287         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10288         if (t->currentskinframe->qpixels)
10289                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10290         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10291         if (!t->basetexture)
10292                 t->basetexture = r_texture_notexture;
10293         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10294         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10295         t->nmaptexture = t->currentskinframe->nmap;
10296         if (!t->nmaptexture)
10297                 t->nmaptexture = r_texture_blanknormalmap;
10298         t->glosstexture = r_texture_black;
10299         t->glowtexture = t->currentskinframe->glow;
10300         t->fogtexture = t->currentskinframe->fog;
10301         t->reflectmasktexture = t->currentskinframe->reflect;
10302         if (t->backgroundnumskinframes)
10303         {
10304                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10305                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10306                 t->backgroundglosstexture = r_texture_black;
10307                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10308                 if (!t->backgroundnmaptexture)
10309                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10310         }
10311         else
10312         {
10313                 t->backgroundbasetexture = r_texture_white;
10314                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10315                 t->backgroundglosstexture = r_texture_black;
10316                 t->backgroundglowtexture = NULL;
10317         }
10318         t->specularpower = r_shadow_glossexponent.value;
10319         // TODO: store reference values for these in the texture?
10320         t->specularscale = 0;
10321         if (r_shadow_gloss.integer > 0)
10322         {
10323                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10324                 {
10325                         if (r_shadow_glossintensity.value > 0)
10326                         {
10327                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10328                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10329                                 t->specularscale = r_shadow_glossintensity.value;
10330                         }
10331                 }
10332                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10333                 {
10334                         t->glosstexture = r_texture_white;
10335                         t->backgroundglosstexture = r_texture_white;
10336                         t->specularscale = r_shadow_gloss2intensity.value;
10337                         t->specularpower = r_shadow_gloss2exponent.value;
10338                 }
10339         }
10340         t->specularscale *= t->specularscalemod;
10341         t->specularpower *= t->specularpowermod;
10342
10343         // lightmaps mode looks bad with dlights using actual texturing, so turn
10344         // off the colormap and glossmap, but leave the normalmap on as it still
10345         // accurately represents the shading involved
10346         if (gl_lightmaps.integer)
10347         {
10348                 t->basetexture = r_texture_grey128;
10349                 t->pantstexture = r_texture_black;
10350                 t->shirttexture = r_texture_black;
10351                 t->nmaptexture = r_texture_blanknormalmap;
10352                 t->glosstexture = r_texture_black;
10353                 t->glowtexture = NULL;
10354                 t->fogtexture = NULL;
10355                 t->reflectmasktexture = NULL;
10356                 t->backgroundbasetexture = NULL;
10357                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10358                 t->backgroundglosstexture = r_texture_black;
10359                 t->backgroundglowtexture = NULL;
10360                 t->specularscale = 0;
10361                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10362         }
10363
10364         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10365         VectorClear(t->dlightcolor);
10366         t->currentnumlayers = 0;
10367         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10368         {
10369                 int blendfunc1, blendfunc2;
10370                 qboolean depthmask;
10371                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10372                 {
10373                         blendfunc1 = GL_SRC_ALPHA;
10374                         blendfunc2 = GL_ONE;
10375                 }
10376                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10377                 {
10378                         blendfunc1 = GL_SRC_ALPHA;
10379                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10380                 }
10381                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10382                 {
10383                         blendfunc1 = t->customblendfunc[0];
10384                         blendfunc2 = t->customblendfunc[1];
10385                 }
10386                 else
10387                 {
10388                         blendfunc1 = GL_ONE;
10389                         blendfunc2 = GL_ZERO;
10390                 }
10391                 // don't colormod evilblend textures
10392                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10393                         VectorSet(t->lightmapcolor, 1, 1, 1);
10394                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10395                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10396                 {
10397                         // fullbright is not affected by r_refdef.lightmapintensity
10398                         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]);
10399                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10400                                 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]);
10401                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10402                                 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]);
10403                 }
10404                 else
10405                 {
10406                         vec3_t ambientcolor;
10407                         float colorscale;
10408                         // set the color tint used for lights affecting this surface
10409                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10410                         colorscale = 2;
10411                         // q3bsp has no lightmap updates, so the lightstylevalue that
10412                         // would normally be baked into the lightmap must be
10413                         // applied to the color
10414                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10415                         if (model->type == mod_brushq3)
10416                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10417                         colorscale *= r_refdef.lightmapintensity;
10418                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10419                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10420                         // basic lit geometry
10421                         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]);
10422                         // add pants/shirt if needed
10423                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10424                                 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]);
10425                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10426                                 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]);
10427                         // now add ambient passes if needed
10428                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10429                         {
10430                                 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]);
10431                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10432                                         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]);
10433                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10434                                         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]);
10435                         }
10436                 }
10437                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10438                         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]);
10439                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10440                 {
10441                         // if this is opaque use alpha blend which will darken the earlier
10442                         // passes cheaply.
10443                         //
10444                         // if this is an alpha blended material, all the earlier passes
10445                         // were darkened by fog already, so we only need to add the fog
10446                         // color ontop through the fog mask texture
10447                         //
10448                         // if this is an additive blended material, all the earlier passes
10449                         // were darkened by fog already, and we should not add fog color
10450                         // (because the background was not darkened, there is no fog color
10451                         // that was lost behind it).
10452                         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]);
10453                 }
10454         }
10455
10456         return t->currentframe;
10457 }
10458
10459 rsurfacestate_t rsurface;
10460
10461 void R_Mesh_ResizeArrays(int newvertices)
10462 {
10463         unsigned char *base;
10464         size_t size;
10465         if (rsurface.array_size >= newvertices)
10466                 return;
10467         if (rsurface.array_base)
10468                 Mem_Free(rsurface.array_base);
10469         rsurface.array_size = (newvertices + 1023) & ~1023;
10470         size = 0;
10471         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10472         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10473         size += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10474         size += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10475         size += rsurface.array_size * sizeof(float[3]);
10476         size += rsurface.array_size * sizeof(float[3]);
10477         size += rsurface.array_size * sizeof(float[3]);
10478         size += rsurface.array_size * sizeof(float[3]);
10479         size += rsurface.array_size * sizeof(float[3]);
10480         size += rsurface.array_size * sizeof(float[3]);
10481         size += rsurface.array_size * sizeof(float[3]);
10482         size += rsurface.array_size * sizeof(float[3]);
10483         size += rsurface.array_size * sizeof(float[4]);
10484         size += rsurface.array_size * sizeof(float[2]);
10485         size += rsurface.array_size * sizeof(float[2]);
10486         size += rsurface.array_size * sizeof(float[4]);
10487         size += rsurface.array_size * sizeof(int[3]);
10488         size += rsurface.array_size * sizeof(unsigned short[3]);
10489         rsurface.array_base = base = (unsigned char *)Mem_Alloc(r_main_mempool, size);
10490         rsurface.array_modelvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexmesh);
10491         rsurface.array_batchvertexmesh         = (r_vertexmesh_t     *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexmesh);
10492         rsurface.array_modelvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_modelvertexposition);
10493         rsurface.array_batchvertexposition     = (r_vertexposition_t *)base;base += rsurface.array_size * sizeof(*rsurface.array_batchvertexposition);
10494         rsurface.array_modelvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10495         rsurface.array_modelsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10496         rsurface.array_modeltvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10497         rsurface.array_modelnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10498         rsurface.array_batchvertex3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10499         rsurface.array_batchsvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10500         rsurface.array_batchtvector3f          = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10501         rsurface.array_batchnormal3f           = (float              *)base;base += rsurface.array_size * sizeof(float[3]);
10502         rsurface.array_batchlightmapcolor4f    = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10503         rsurface.array_batchtexcoordtexture2f  = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10504         rsurface.array_batchtexcoordlightmap2f = (float              *)base;base += rsurface.array_size * sizeof(float[2]);
10505         rsurface.array_passcolor4f             = (float              *)base;base += rsurface.array_size * sizeof(float[4]);
10506         rsurface.array_batchelement3i          = (int                *)base;base += rsurface.array_size * sizeof(int[3]);
10507         rsurface.array_batchelement3s          = (unsigned short     *)base;base += rsurface.array_size * sizeof(unsigned short[3]);
10508 }
10509
10510 void RSurf_ActiveWorldEntity(void)
10511 {
10512         dp_model_t *model = r_refdef.scene.worldmodel;
10513         //if (rsurface.entity == r_refdef.scene.worldentity)
10514         //      return;
10515         rsurface.entity = r_refdef.scene.worldentity;
10516         rsurface.skeleton = NULL;
10517         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10518         rsurface.ent_skinnum = 0;
10519         rsurface.ent_qwskin = -1;
10520         rsurface.ent_shadertime = 0;
10521         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10522         if (rsurface.array_size < model->surfmesh.num_vertices)
10523                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10524         rsurface.matrix = identitymatrix;
10525         rsurface.inversematrix = identitymatrix;
10526         rsurface.matrixscale = 1;
10527         rsurface.inversematrixscale = 1;
10528         R_EntityMatrix(&identitymatrix);
10529         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10530         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10531         rsurface.fograngerecip = r_refdef.fograngerecip;
10532         rsurface.fogheightfade = r_refdef.fogheightfade;
10533         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10534         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10535         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10536         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10537         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10538         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10539         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10540         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10541         rsurface.colormod[3] = 1;
10542         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);
10543         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10544         rsurface.frameblend[0].lerp = 1;
10545         rsurface.ent_alttextures = false;
10546         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10547         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10548         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10549         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10550         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10551         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10552         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10553         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10554         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10555         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10556         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10557         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10558         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10559         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10560         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10561         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10562         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10563         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10564         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10565         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10566         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10567         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10568         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10569         rsurface.modelelement3i = model->surfmesh.data_element3i;
10570         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10571         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10572         rsurface.modelelement3s = model->surfmesh.data_element3s;
10573         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10574         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10575         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10576         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10577         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10578         rsurface.modelsurfaces = model->data_surfaces;
10579         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10580         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10581         rsurface.modelvertexposition = model->surfmesh.vertexposition;
10582         rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10583         rsurface.modelgeneratedvertex = false;
10584         rsurface.batchgeneratedvertex = false;
10585         rsurface.batchfirstvertex = 0;
10586         rsurface.batchnumvertices = 0;
10587         rsurface.batchfirsttriangle = 0;
10588         rsurface.batchnumtriangles = 0;
10589         rsurface.batchvertex3f  = NULL;
10590         rsurface.batchvertex3f_vertexbuffer = NULL;
10591         rsurface.batchvertex3f_bufferoffset = 0;
10592         rsurface.batchsvector3f = NULL;
10593         rsurface.batchsvector3f_vertexbuffer = NULL;
10594         rsurface.batchsvector3f_bufferoffset = 0;
10595         rsurface.batchtvector3f = NULL;
10596         rsurface.batchtvector3f_vertexbuffer = NULL;
10597         rsurface.batchtvector3f_bufferoffset = 0;
10598         rsurface.batchnormal3f  = NULL;
10599         rsurface.batchnormal3f_vertexbuffer = NULL;
10600         rsurface.batchnormal3f_bufferoffset = 0;
10601         rsurface.batchlightmapcolor4f = NULL;
10602         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10603         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10604         rsurface.batchtexcoordtexture2f = NULL;
10605         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10606         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10607         rsurface.batchtexcoordlightmap2f = NULL;
10608         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10609         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10610         rsurface.batchvertexmesh = NULL;
10611         rsurface.batchvertexmeshbuffer = NULL;
10612         rsurface.batchvertexposition = NULL;
10613         rsurface.batchvertexpositionbuffer = NULL;
10614         rsurface.batchelement3i = NULL;
10615         rsurface.batchelement3i_indexbuffer = NULL;
10616         rsurface.batchelement3i_bufferoffset = 0;
10617         rsurface.batchelement3s = NULL;
10618         rsurface.batchelement3s_indexbuffer = NULL;
10619         rsurface.batchelement3s_bufferoffset = 0;
10620         rsurface.passcolor4f = NULL;
10621         rsurface.passcolor4f_vertexbuffer = NULL;
10622         rsurface.passcolor4f_bufferoffset = 0;
10623 }
10624
10625 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10626 {
10627         dp_model_t *model = ent->model;
10628         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10629         //      return;
10630         rsurface.entity = (entity_render_t *)ent;
10631         rsurface.skeleton = ent->skeleton;
10632         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10633         rsurface.ent_skinnum = ent->skinnum;
10634         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;
10635         rsurface.ent_shadertime = ent->shadertime;
10636         rsurface.ent_flags = ent->flags;
10637         if (rsurface.array_size < model->surfmesh.num_vertices)
10638                 R_Mesh_ResizeArrays(model->surfmesh.num_vertices);
10639         rsurface.matrix = ent->matrix;
10640         rsurface.inversematrix = ent->inversematrix;
10641         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10642         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10643         R_EntityMatrix(&rsurface.matrix);
10644         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10645         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10646         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10647         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10648         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10649         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10650         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10651         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10652         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10653         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10654         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10655         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10656         rsurface.colormod[3] = ent->alpha;
10657         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10658         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10659         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10660         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10661         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10662         if (ent->model->brush.submodel && !prepass)
10663         {
10664                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10665                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10666         }
10667         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10668         {
10669                 if (ent->animcache_vertex3f && !r_framedata_failed)
10670                 {
10671                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10672                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10673                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10674                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10675                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10676                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10677                         rsurface.modelvertexposition = ent->animcache_vertexposition;
10678                         rsurface.modelvertexpositionbuffer = ent->animcache_vertexpositionbuffer;
10679                 }
10680                 else if (wanttangents)
10681                 {
10682                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10683                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10684                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10685                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10686                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, rsurface.array_modelsvector3f, rsurface.array_modeltvector3f);
10687                         rsurface.modelvertexmesh = NULL;
10688                         rsurface.modelvertexmeshbuffer = NULL;
10689                         rsurface.modelvertexposition = NULL;
10690                         rsurface.modelvertexpositionbuffer = NULL;
10691                 }
10692                 else if (wantnormals)
10693                 {
10694                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10695                         rsurface.modelsvector3f = NULL;
10696                         rsurface.modeltvector3f = NULL;
10697                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10698                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, rsurface.array_modelnormal3f, NULL, NULL);
10699                         rsurface.modelvertexmesh = NULL;
10700                         rsurface.modelvertexmeshbuffer = NULL;
10701                         rsurface.modelvertexposition = NULL;
10702                         rsurface.modelvertexpositionbuffer = NULL;
10703                 }
10704                 else
10705                 {
10706                         rsurface.modelvertex3f = rsurface.array_modelvertex3f;
10707                         rsurface.modelsvector3f = NULL;
10708                         rsurface.modeltvector3f = NULL;
10709                         rsurface.modelnormal3f = NULL;
10710                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.array_modelvertex3f, NULL, NULL, NULL);
10711                         rsurface.modelvertexmesh = NULL;
10712                         rsurface.modelvertexmeshbuffer = NULL;
10713                         rsurface.modelvertexposition = NULL;
10714                         rsurface.modelvertexpositionbuffer = NULL;
10715                 }
10716                 rsurface.modelvertex3f_vertexbuffer = 0;
10717                 rsurface.modelvertex3f_bufferoffset = 0;
10718                 rsurface.modelsvector3f_vertexbuffer = 0;
10719                 rsurface.modelsvector3f_bufferoffset = 0;
10720                 rsurface.modeltvector3f_vertexbuffer = 0;
10721                 rsurface.modeltvector3f_bufferoffset = 0;
10722                 rsurface.modelnormal3f_vertexbuffer = 0;
10723                 rsurface.modelnormal3f_bufferoffset = 0;
10724                 rsurface.modelgeneratedvertex = true;
10725         }
10726         else
10727         {
10728                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10729                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10730                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10731                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10732                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10733                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10734                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10735                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10736                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10737                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10738                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10739                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10740                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10741                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10742                 rsurface.modelvertexposition = model->surfmesh.vertexposition;
10743                 rsurface.modelvertexpositionbuffer = model->surfmesh.vertexpositionbuffer;
10744                 rsurface.modelgeneratedvertex = false;
10745         }
10746         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10747         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10748         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10749         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10750         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10751         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10752         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10753         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10754         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10755         rsurface.modelelement3i = model->surfmesh.data_element3i;
10756         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10757         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10758         rsurface.modelelement3s = model->surfmesh.data_element3s;
10759         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10760         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10761         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10762         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10763         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10764         rsurface.modelsurfaces = model->data_surfaces;
10765         rsurface.batchgeneratedvertex = false;
10766         rsurface.batchfirstvertex = 0;
10767         rsurface.batchnumvertices = 0;
10768         rsurface.batchfirsttriangle = 0;
10769         rsurface.batchnumtriangles = 0;
10770         rsurface.batchvertex3f  = NULL;
10771         rsurface.batchvertex3f_vertexbuffer = NULL;
10772         rsurface.batchvertex3f_bufferoffset = 0;
10773         rsurface.batchsvector3f = NULL;
10774         rsurface.batchsvector3f_vertexbuffer = NULL;
10775         rsurface.batchsvector3f_bufferoffset = 0;
10776         rsurface.batchtvector3f = NULL;
10777         rsurface.batchtvector3f_vertexbuffer = NULL;
10778         rsurface.batchtvector3f_bufferoffset = 0;
10779         rsurface.batchnormal3f  = NULL;
10780         rsurface.batchnormal3f_vertexbuffer = NULL;
10781         rsurface.batchnormal3f_bufferoffset = 0;
10782         rsurface.batchlightmapcolor4f = NULL;
10783         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10784         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10785         rsurface.batchtexcoordtexture2f = NULL;
10786         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10787         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10788         rsurface.batchtexcoordlightmap2f = NULL;
10789         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10790         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10791         rsurface.batchvertexmesh = NULL;
10792         rsurface.batchvertexmeshbuffer = NULL;
10793         rsurface.batchvertexposition = NULL;
10794         rsurface.batchvertexpositionbuffer = NULL;
10795         rsurface.batchelement3i = NULL;
10796         rsurface.batchelement3i_indexbuffer = NULL;
10797         rsurface.batchelement3i_bufferoffset = 0;
10798         rsurface.batchelement3s = NULL;
10799         rsurface.batchelement3s_indexbuffer = NULL;
10800         rsurface.batchelement3s_bufferoffset = 0;
10801         rsurface.passcolor4f = NULL;
10802         rsurface.passcolor4f_vertexbuffer = NULL;
10803         rsurface.passcolor4f_bufferoffset = 0;
10804 }
10805
10806 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)
10807 {
10808         int i;
10809
10810         rsurface.entity = r_refdef.scene.worldentity;
10811         rsurface.skeleton = NULL;
10812         rsurface.ent_skinnum = 0;
10813         rsurface.ent_qwskin = -1;
10814         rsurface.ent_shadertime = shadertime;
10815         rsurface.ent_flags = entflags;
10816         rsurface.modelnumvertices = numvertices;
10817         rsurface.modelnumtriangles = numtriangles;
10818         if (rsurface.array_size < rsurface.modelnumvertices)
10819                 R_Mesh_ResizeArrays(rsurface.modelnumvertices);
10820         rsurface.matrix = *matrix;
10821         rsurface.inversematrix = *inversematrix;
10822         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10823         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10824         R_EntityMatrix(&rsurface.matrix);
10825         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10826         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10827         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10828         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10829         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10830         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10831         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10832         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10833         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10834         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10835         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10836         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10837         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);
10838         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10839         rsurface.frameblend[0].lerp = 1;
10840         rsurface.ent_alttextures = false;
10841         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10842         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10843         if (wanttangents)
10844         {
10845                 rsurface.modelvertex3f = vertex3f;
10846                 rsurface.modelsvector3f = svector3f ? svector3f : rsurface.array_modelsvector3f;
10847                 rsurface.modeltvector3f = tvector3f ? tvector3f : rsurface.array_modeltvector3f;
10848                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10849         }
10850         else if (wantnormals)
10851         {
10852                 rsurface.modelvertex3f = vertex3f;
10853                 rsurface.modelsvector3f = NULL;
10854                 rsurface.modeltvector3f = NULL;
10855                 rsurface.modelnormal3f = normal3f ? normal3f : rsurface.array_modelnormal3f;
10856         }
10857         else
10858         {
10859                 rsurface.modelvertex3f = vertex3f;
10860                 rsurface.modelsvector3f = NULL;
10861                 rsurface.modeltvector3f = NULL;
10862                 rsurface.modelnormal3f = NULL;
10863         }
10864         rsurface.modelvertexmesh = NULL;
10865         rsurface.modelvertexmeshbuffer = NULL;
10866         rsurface.modelvertexposition = NULL;
10867         rsurface.modelvertexpositionbuffer = NULL;
10868         rsurface.modelvertex3f_vertexbuffer = 0;
10869         rsurface.modelvertex3f_bufferoffset = 0;
10870         rsurface.modelsvector3f_vertexbuffer = 0;
10871         rsurface.modelsvector3f_bufferoffset = 0;
10872         rsurface.modeltvector3f_vertexbuffer = 0;
10873         rsurface.modeltvector3f_bufferoffset = 0;
10874         rsurface.modelnormal3f_vertexbuffer = 0;
10875         rsurface.modelnormal3f_bufferoffset = 0;
10876         rsurface.modelgeneratedvertex = true;
10877         rsurface.modellightmapcolor4f  = color4f;
10878         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10879         rsurface.modellightmapcolor4f_bufferoffset = 0;
10880         rsurface.modeltexcoordtexture2f  = texcoord2f;
10881         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10882         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10883         rsurface.modeltexcoordlightmap2f  = NULL;
10884         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10885         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10886         rsurface.modelelement3i = element3i;
10887         rsurface.modelelement3i_indexbuffer = NULL;
10888         rsurface.modelelement3i_bufferoffset = 0;
10889         rsurface.modelelement3s = element3s;
10890         rsurface.modelelement3s_indexbuffer = NULL;
10891         rsurface.modelelement3s_bufferoffset = 0;
10892         rsurface.modellightmapoffsets = NULL;
10893         rsurface.modelsurfaces = NULL;
10894         rsurface.batchgeneratedvertex = false;
10895         rsurface.batchfirstvertex = 0;
10896         rsurface.batchnumvertices = 0;
10897         rsurface.batchfirsttriangle = 0;
10898         rsurface.batchnumtriangles = 0;
10899         rsurface.batchvertex3f  = NULL;
10900         rsurface.batchvertex3f_vertexbuffer = NULL;
10901         rsurface.batchvertex3f_bufferoffset = 0;
10902         rsurface.batchsvector3f = NULL;
10903         rsurface.batchsvector3f_vertexbuffer = NULL;
10904         rsurface.batchsvector3f_bufferoffset = 0;
10905         rsurface.batchtvector3f = NULL;
10906         rsurface.batchtvector3f_vertexbuffer = NULL;
10907         rsurface.batchtvector3f_bufferoffset = 0;
10908         rsurface.batchnormal3f  = NULL;
10909         rsurface.batchnormal3f_vertexbuffer = NULL;
10910         rsurface.batchnormal3f_bufferoffset = 0;
10911         rsurface.batchlightmapcolor4f = NULL;
10912         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10913         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10914         rsurface.batchtexcoordtexture2f = NULL;
10915         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10916         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10917         rsurface.batchtexcoordlightmap2f = NULL;
10918         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10919         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10920         rsurface.batchvertexmesh = NULL;
10921         rsurface.batchvertexmeshbuffer = NULL;
10922         rsurface.batchvertexposition = NULL;
10923         rsurface.batchvertexpositionbuffer = NULL;
10924         rsurface.batchelement3i = NULL;
10925         rsurface.batchelement3i_indexbuffer = NULL;
10926         rsurface.batchelement3i_bufferoffset = 0;
10927         rsurface.batchelement3s = NULL;
10928         rsurface.batchelement3s_indexbuffer = NULL;
10929         rsurface.batchelement3s_bufferoffset = 0;
10930         rsurface.passcolor4f = NULL;
10931         rsurface.passcolor4f_vertexbuffer = NULL;
10932         rsurface.passcolor4f_bufferoffset = 0;
10933
10934         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10935         {
10936                 if ((wantnormals || wanttangents) && !normal3f)
10937                 {
10938                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.array_modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10939                         rsurface.modelnormal3f = rsurface.array_modelnormal3f;
10940                 }
10941                 if (wanttangents && !svector3f)
10942                 {
10943                         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);
10944                         rsurface.modelsvector3f = rsurface.array_modelsvector3f;
10945                         rsurface.modeltvector3f = rsurface.array_modeltvector3f;
10946                 }
10947         }
10948
10949         // now convert arrays into vertexmesh structs
10950         for (i = 0;i < numvertices;i++)
10951         {
10952                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexposition[i].vertex3f);
10953                 VectorCopy(rsurface.modelvertex3f + 3*i, rsurface.array_modelvertexmesh[i].vertex3f);
10954                 if (rsurface.modelsvector3f)
10955                         VectorCopy(rsurface.modelsvector3f + 3*i, rsurface.array_modelvertexmesh[i].svector3f);
10956                 if (rsurface.modeltvector3f)
10957                         VectorCopy(rsurface.modeltvector3f + 3*i, rsurface.array_modelvertexmesh[i].tvector3f);
10958                 if (rsurface.modelnormal3f)
10959                         VectorCopy(rsurface.modelnormal3f + 3*i, rsurface.array_modelvertexmesh[i].normal3f);
10960                 if (rsurface.modellightmapcolor4f)
10961                         Vector4Scale(rsurface.modellightmapcolor4f + 4*i, 255.0f, rsurface.array_modelvertexmesh[i].color4ub);
10962                 if (rsurface.modeltexcoordtexture2f)
10963                         Vector2Copy(rsurface.modeltexcoordtexture2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordtexture2f);
10964                 if (rsurface.modeltexcoordlightmap2f)
10965                         Vector2Copy(rsurface.modeltexcoordlightmap2f + 2*i, rsurface.array_modelvertexmesh[i].texcoordlightmap2f);
10966         }
10967 }
10968
10969 float RSurf_FogPoint(const float *v)
10970 {
10971         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10972         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10973         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10974         float FogHeightFade = r_refdef.fogheightfade;
10975         float fogfrac;
10976         unsigned int fogmasktableindex;
10977         if (r_refdef.fogplaneviewabove)
10978                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10979         else
10980                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10981         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10982         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10983 }
10984
10985 float RSurf_FogVertex(const float *v)
10986 {
10987         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10988         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10989         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10990         float FogHeightFade = rsurface.fogheightfade;
10991         float fogfrac;
10992         unsigned int fogmasktableindex;
10993         if (r_refdef.fogplaneviewabove)
10994                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10995         else
10996                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10997         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10998         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10999 }
11000
11001 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11002 {
11003         int i;
11004         for (i = 0;i < numelements;i++)
11005                 outelement3i[i] = inelement3i[i] + adjust;
11006 }
11007
11008 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11009 extern cvar_t gl_vbo;
11010 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11011 {
11012         int deformindex;
11013         int firsttriangle;
11014         int numtriangles;
11015         int firstvertex;
11016         int endvertex;
11017         int numvertices;
11018         int surfacefirsttriangle;
11019         int surfacenumtriangles;
11020         int surfacefirstvertex;
11021         int surfaceendvertex;
11022         int surfacenumvertices;
11023         int surfaceadjustvertex;
11024         int needsupdate;
11025         int i, j;
11026         qboolean gaps;
11027         qboolean dynamicvertex;
11028         float amplitude;
11029         float animpos;
11030         float scale;
11031         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11032         float waveparms[4];
11033         q3shaderinfo_deform_t *deform;
11034         const msurface_t *surface, *firstsurface;
11035         r_vertexposition_t *vertexposition;
11036         r_vertexmesh_t *vertexmesh;
11037         if (!texturenumsurfaces)
11038                 return;
11039         // find vertex range of this surface batch
11040         gaps = false;
11041         firstsurface = texturesurfacelist[0];
11042         firsttriangle = firstsurface->num_firsttriangle;
11043         numtriangles = 0;
11044         firstvertex = endvertex = firstsurface->num_firstvertex;
11045         for (i = 0;i < texturenumsurfaces;i++)
11046         {
11047                 surface = texturesurfacelist[i];
11048                 if (surface != firstsurface + i)
11049                         gaps = true;
11050                 surfacefirstvertex = surface->num_firstvertex;
11051                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11052                 surfacenumtriangles = surface->num_triangles;
11053                 if (firstvertex > surfacefirstvertex)
11054                         firstvertex = surfacefirstvertex;
11055                 if (endvertex < surfaceendvertex)
11056                         endvertex = surfaceendvertex;
11057                 numtriangles += surfacenumtriangles;
11058         }
11059         if (!numtriangles)
11060                 return;
11061
11062         // we now know the vertex range used, and if there are any gaps in it
11063         rsurface.batchfirstvertex = firstvertex;
11064         rsurface.batchnumvertices = endvertex - firstvertex;
11065         rsurface.batchfirsttriangle = firsttriangle;
11066         rsurface.batchnumtriangles = numtriangles;
11067
11068         // this variable holds flags for which properties have been updated that
11069         // may require regenerating vertexmesh or vertexposition arrays...
11070         needsupdate = 0;
11071
11072         // check if any dynamic vertex processing must occur
11073         dynamicvertex = false;
11074
11075         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11076                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_NOGAPS;
11077         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11078         {
11079                 switch (deform->deform)
11080                 {
11081                 default:
11082                 case Q3DEFORM_PROJECTIONSHADOW:
11083                 case Q3DEFORM_TEXT0:
11084                 case Q3DEFORM_TEXT1:
11085                 case Q3DEFORM_TEXT2:
11086                 case Q3DEFORM_TEXT3:
11087                 case Q3DEFORM_TEXT4:
11088                 case Q3DEFORM_TEXT5:
11089                 case Q3DEFORM_TEXT6:
11090                 case Q3DEFORM_TEXT7:
11091                 case Q3DEFORM_NONE:
11092                         break;
11093                 case Q3DEFORM_AUTOSPRITE:
11094                         dynamicvertex = true;
11095                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11096                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11097                         break;
11098                 case Q3DEFORM_AUTOSPRITE2:
11099                         dynamicvertex = true;
11100                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11101                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11102                         break;
11103                 case Q3DEFORM_NORMAL:
11104                         dynamicvertex = true;
11105                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11106                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11107                         break;
11108                 case Q3DEFORM_WAVE:
11109                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11110                                 break; // if wavefunc is a nop, ignore this transform
11111                         dynamicvertex = true;
11112                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11113                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11114                         break;
11115                 case Q3DEFORM_BULGE:
11116                         dynamicvertex = true;
11117                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11118                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11119                         break;
11120                 case Q3DEFORM_MOVE:
11121                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11122                                 break; // if wavefunc is a nop, ignore this transform
11123                         dynamicvertex = true;
11124                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11125                         needsupdate |= BATCHNEED_VERTEXPOSITION | BATCHNEED_VERTEXMESH_VERTEX;
11126                         break;
11127                 }
11128         }
11129         switch(rsurface.texture->tcgen.tcgen)
11130         {
11131         default:
11132         case Q3TCGEN_TEXTURE:
11133                 break;
11134         case Q3TCGEN_LIGHTMAP:
11135                 dynamicvertex = true;
11136                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11137                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11138                 break;
11139         case Q3TCGEN_VECTOR:
11140                 dynamicvertex = true;
11141                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11142                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11143                 break;
11144         case Q3TCGEN_ENVIRONMENT:
11145                 dynamicvertex = true;
11146                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11147                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11148                 break;
11149         }
11150         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11151         {
11152                 dynamicvertex = true;
11153                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11154                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11155         }
11156
11157         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11158         {
11159                 dynamicvertex = true;
11160                 batchneed |= BATCHNEED_NOGAPS;
11161                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11162         }
11163
11164         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11165         {
11166                 dynamicvertex = true;
11167                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11168                 needsupdate |= (batchneed & BATCHNEED_VERTEXPOSITION);
11169         }
11170
11171         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11172         {
11173                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11174                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11175                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11176                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11177                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11178                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11179                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11180         }
11181
11182         // when the model data has no vertex buffer (dynamic mesh), we need to
11183         // eliminate gaps
11184         if (!rsurface.modelvertexmeshbuffer)
11185                 batchneed |= BATCHNEED_NOGAPS;
11186
11187         // if needsupdate, we have to do a dynamic vertex batch for sure
11188         if (needsupdate & batchneed)
11189                 dynamicvertex = true;
11190
11191         // see if we need to build vertexmesh from arrays
11192         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11193                 dynamicvertex = true;
11194
11195         // see if we need to build vertexposition from arrays
11196         if (!rsurface.modelvertexposition && (batchneed & BATCHNEED_VERTEXPOSITION))
11197                 dynamicvertex = true;
11198
11199         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11200         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11201                 dynamicvertex = true;
11202
11203         // if there is a chance of animated vertex colors, it's a dynamic batch
11204         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11205                 dynamicvertex = true;
11206
11207         rsurface.batchvertex3f = rsurface.modelvertex3f;
11208         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11209         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11210         rsurface.batchsvector3f = rsurface.modelsvector3f;
11211         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11212         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11213         rsurface.batchtvector3f = rsurface.modeltvector3f;
11214         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11215         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11216         rsurface.batchnormal3f = rsurface.modelnormal3f;
11217         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11218         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11219         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11220         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11221         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11222         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11223         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11224         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11225         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11226         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11227         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11228         rsurface.batchvertexposition = rsurface.modelvertexposition;
11229         rsurface.batchvertexpositionbuffer = rsurface.modelvertexpositionbuffer;
11230         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11231         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11232         rsurface.batchelement3i = rsurface.modelelement3i;
11233         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11234         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11235         rsurface.batchelement3s = rsurface.modelelement3s;
11236         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11237         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11238
11239         // if any dynamic vertex processing has to occur in software, we copy the
11240         // entire surface list together before processing to rebase the vertices
11241         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11242         //
11243         // if any gaps exist and we do not have a static vertex buffer, we have to
11244         // copy the surface list together to avoid wasting upload bandwidth on the
11245         // vertices in the gaps.
11246         //
11247         // if gaps exist and we have a static vertex buffer, we still have to
11248         // combine the index buffer ranges into one dynamic index buffer.
11249         //
11250         // in all cases we end up with data that can be drawn in one call.
11251
11252         if (!dynamicvertex)
11253         {
11254                 // static vertex data, just set pointers...
11255                 rsurface.batchgeneratedvertex = false;
11256                 // if there are gaps, we want to build a combined index buffer,
11257                 // otherwise use the original static buffer with an appropriate offset
11258                 if (gaps)
11259                 {
11260                         firsttriangle = 0;
11261                         numtriangles = 0;
11262                         for (i = 0;i < texturenumsurfaces;i++)
11263                         {
11264                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11265                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11266                                 memcpy(rsurface.array_batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11267                                 numtriangles += surfacenumtriangles;
11268                         }
11269                         rsurface.batchelement3i = rsurface.array_batchelement3i;
11270                         rsurface.batchelement3i_indexbuffer = NULL;
11271                         rsurface.batchelement3i_bufferoffset = 0;
11272                         rsurface.batchelement3s = NULL;
11273                         rsurface.batchelement3s_indexbuffer = NULL;
11274                         rsurface.batchelement3s_bufferoffset = 0;
11275                         if (endvertex <= 65536)
11276                         {
11277                                 rsurface.batchelement3s = rsurface.array_batchelement3s;
11278                                 for (i = 0;i < numtriangles*3;i++)
11279                                         rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11280                         }
11281                         rsurface.batchfirsttriangle = firsttriangle;
11282                         rsurface.batchnumtriangles = numtriangles;
11283                 }
11284                 return;
11285         }
11286
11287         // something needs software processing, do it for real...
11288         // we only directly handle interleaved array data in this case...
11289         rsurface.batchgeneratedvertex = true;
11290
11291         // now copy the vertex data into a combined array and make an index array
11292         // (this is what Quake3 does all the time)
11293         //if (gaps || rsurface.batchfirstvertex)
11294         {
11295                 rsurface.batchvertexposition = NULL;
11296                 rsurface.batchvertexpositionbuffer = NULL;
11297                 rsurface.batchvertexmesh = NULL;
11298                 rsurface.batchvertexmeshbuffer = NULL;
11299                 rsurface.batchvertex3f = NULL;
11300                 rsurface.batchvertex3f_vertexbuffer = NULL;
11301                 rsurface.batchvertex3f_bufferoffset = 0;
11302                 rsurface.batchsvector3f = NULL;
11303                 rsurface.batchsvector3f_vertexbuffer = NULL;
11304                 rsurface.batchsvector3f_bufferoffset = 0;
11305                 rsurface.batchtvector3f = NULL;
11306                 rsurface.batchtvector3f_vertexbuffer = NULL;
11307                 rsurface.batchtvector3f_bufferoffset = 0;
11308                 rsurface.batchnormal3f = NULL;
11309                 rsurface.batchnormal3f_vertexbuffer = NULL;
11310                 rsurface.batchnormal3f_bufferoffset = 0;
11311                 rsurface.batchlightmapcolor4f = NULL;
11312                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11313                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11314                 rsurface.batchtexcoordtexture2f = NULL;
11315                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11316                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11317                 rsurface.batchtexcoordlightmap2f = NULL;
11318                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11319                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11320                 rsurface.batchelement3i = rsurface.array_batchelement3i;
11321                 rsurface.batchelement3i_indexbuffer = NULL;
11322                 rsurface.batchelement3i_bufferoffset = 0;
11323                 rsurface.batchelement3s = NULL;
11324                 rsurface.batchelement3s_indexbuffer = NULL;
11325                 rsurface.batchelement3s_bufferoffset = 0;
11326                 // we'll only be setting up certain arrays as needed
11327                 if (batchneed & BATCHNEED_VERTEXPOSITION)
11328                         rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11329                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11330                         rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11331                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11332                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11333                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11334                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11335                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11336                 {
11337                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11338                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11339                 }
11340                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11341                         rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11342                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11343                         rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11344                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11345                         rsurface.batchtexcoordlightmap2f = rsurface.array_batchtexcoordlightmap2f;
11346                 numvertices = 0;
11347                 numtriangles = 0;
11348                 for (i = 0;i < texturenumsurfaces;i++)
11349                 {
11350                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11351                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11352                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11353                         surfaceadjustvertex = numvertices - surfacefirstvertex;
11354                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11355                         // copy only the data requested
11356                         if ((batchneed & BATCHNEED_VERTEXPOSITION) && rsurface.modelvertexposition)
11357                                 memcpy(rsurface.array_batchvertexposition + numvertices, rsurface.modelvertexposition + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexposition[0]));
11358                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11359                                 memcpy(rsurface.array_batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11360                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11361                         {
11362                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11363                                         memcpy(rsurface.array_batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11364                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11365                                         memcpy(rsurface.array_batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11366                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11367                                 {
11368                                         memcpy(rsurface.array_batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11369                                         memcpy(rsurface.array_batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11370                                 }
11371                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11372                                         memcpy(rsurface.array_batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11373                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11374                                         memcpy(rsurface.array_batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11375                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11376                                         memcpy(rsurface.array_batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11377                         }
11378                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.array_batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11379                         numvertices += surfacenumvertices;
11380                         numtriangles += surfacenumtriangles;
11381                 }
11382
11383                 // generate a 16bit index array as well if possible
11384                 // (in general, dynamic batches fit)
11385                 if (numvertices <= 65536)
11386                 {
11387                         rsurface.batchelement3s = rsurface.array_batchelement3s;
11388                         for (i = 0;i < numtriangles*3;i++)
11389                                 rsurface.array_batchelement3s[i] = rsurface.array_batchelement3i[i];
11390                 }
11391
11392                 // since we've copied everything, the batch now starts at 0
11393                 rsurface.batchfirstvertex = 0;
11394                 rsurface.batchnumvertices = numvertices;
11395                 rsurface.batchfirsttriangle = 0;
11396                 rsurface.batchnumtriangles = numtriangles;
11397         }
11398
11399         // q1bsp surfaces rendered in vertex color mode have to have colors
11400         // calculated based on lightstyles
11401         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11402         {
11403                 // generate color arrays for the surfaces in this list
11404                 int c[4];
11405                 int scale;
11406                 int size3;
11407                 const int *offsets;
11408                 const unsigned char *lm;
11409                 numvertices = 0;
11410                 rsurface.batchlightmapcolor4f = rsurface.array_batchlightmapcolor4f;
11411                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11412                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11413                 for (i = 0;i < texturenumsurfaces;i++)
11414                 {
11415                         surface = texturesurfacelist[i];
11416                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11417                         surfacenumvertices = surface->num_vertices;
11418                         if (surface->lightmapinfo->samples)
11419                         {
11420                                 for (j = 0;j < surfacenumvertices;j++)
11421                                 {
11422                                         lm = surface->lightmapinfo->samples + offsets[j];
11423                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11424                                         VectorScale(lm, scale, c);
11425                                         if (surface->lightmapinfo->styles[1] != 255)
11426                                         {
11427                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11428                                                 lm += size3;
11429                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11430                                                 VectorMA(c, scale, lm, c);
11431                                                 if (surface->lightmapinfo->styles[2] != 255)
11432                                                 {
11433                                                         lm += size3;
11434                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11435                                                         VectorMA(c, scale, lm, c);
11436                                                         if (surface->lightmapinfo->styles[3] != 255)
11437                                                         {
11438                                                                 lm += size3;
11439                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11440                                                                 VectorMA(c, scale, lm, c);
11441                                                         }
11442                                                 }
11443                                         }
11444                                         c[0] >>= 15;
11445                                         c[1] >>= 15;
11446                                         c[2] >>= 15;
11447                                         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);
11448                                         numvertices++;
11449                                 }
11450                         }
11451                         else
11452                         {
11453                                 for (j = 0;j < surfacenumvertices;j++)
11454                                 {
11455                                         Vector4Set(rsurface.array_batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11456                                         numvertices++;
11457                                 }
11458                         }
11459                 }
11460         }
11461
11462         // if vertices are deformed (sprite flares and things in maps, possibly
11463         // water waves, bulges and other deformations), modify the copied vertices
11464         // in place
11465         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11466         {
11467                 switch (deform->deform)
11468                 {
11469                 default:
11470                 case Q3DEFORM_PROJECTIONSHADOW:
11471                 case Q3DEFORM_TEXT0:
11472                 case Q3DEFORM_TEXT1:
11473                 case Q3DEFORM_TEXT2:
11474                 case Q3DEFORM_TEXT3:
11475                 case Q3DEFORM_TEXT4:
11476                 case Q3DEFORM_TEXT5:
11477                 case Q3DEFORM_TEXT6:
11478                 case Q3DEFORM_TEXT7:
11479                 case Q3DEFORM_NONE:
11480                         break;
11481                 case Q3DEFORM_AUTOSPRITE:
11482                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11483                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11484                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11485                         VectorNormalize(newforward);
11486                         VectorNormalize(newright);
11487                         VectorNormalize(newup);
11488                         // a single autosprite surface can contain multiple sprites...
11489                         for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11490                         {
11491                                 VectorClear(center);
11492                                 for (i = 0;i < 4;i++)
11493                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11494                                 VectorScale(center, 0.25f, center);
11495                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11496                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11497                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11498                                 for (i = 0;i < 4;i++)
11499                                 {
11500                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11501                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.array_batchvertex3f + 3*(j+i));
11502                                 }
11503                         }
11504                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11505                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11506                         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);
11507                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11508                         rsurface.batchvertex3f_vertexbuffer = NULL;
11509                         rsurface.batchvertex3f_bufferoffset = 0;
11510                         rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11511                         rsurface.batchsvector3f_vertexbuffer = NULL;
11512                         rsurface.batchsvector3f_bufferoffset = 0;
11513                         rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11514                         rsurface.batchtvector3f_vertexbuffer = NULL;
11515                         rsurface.batchtvector3f_bufferoffset = 0;
11516                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11517                         rsurface.batchnormal3f_vertexbuffer = NULL;
11518                         rsurface.batchnormal3f_bufferoffset = 0;
11519                         break;
11520                 case Q3DEFORM_AUTOSPRITE2:
11521                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11522                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11523                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11524                         VectorNormalize(newforward);
11525                         VectorNormalize(newright);
11526                         VectorNormalize(newup);
11527                         {
11528                                 const float *v1, *v2;
11529                                 vec3_t start, end;
11530                                 float f, l;
11531                                 struct
11532                                 {
11533                                         float length2;
11534                                         const float *v1;
11535                                         const float *v2;
11536                                 }
11537                                 shortest[2];
11538                                 memset(shortest, 0, sizeof(shortest));
11539                                 // a single autosprite surface can contain multiple sprites...
11540                                 for (j = 0;j < rsurface.batchnumvertices - 3;j += 4)
11541                                 {
11542                                         VectorClear(center);
11543                                         for (i = 0;i < 4;i++)
11544                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11545                                         VectorScale(center, 0.25f, center);
11546                                         // find the two shortest edges, then use them to define the
11547                                         // axis vectors for rotating around the central axis
11548                                         for (i = 0;i < 6;i++)
11549                                         {
11550                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11551                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11552                                                 l = VectorDistance2(v1, v2);
11553                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11554                                                 if (v1[2] != v2[2])
11555                                                         l += (1.0f / 1024.0f);
11556                                                 if (shortest[0].length2 > l || i == 0)
11557                                                 {
11558                                                         shortest[1] = shortest[0];
11559                                                         shortest[0].length2 = l;
11560                                                         shortest[0].v1 = v1;
11561                                                         shortest[0].v2 = v2;
11562                                                 }
11563                                                 else if (shortest[1].length2 > l || i == 1)
11564                                                 {
11565                                                         shortest[1].length2 = l;
11566                                                         shortest[1].v1 = v1;
11567                                                         shortest[1].v2 = v2;
11568                                                 }
11569                                         }
11570                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11571                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11572                                         // this calculates the right vector from the shortest edge
11573                                         // and the up vector from the edge midpoints
11574                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11575                                         VectorNormalize(right);
11576                                         VectorSubtract(end, start, up);
11577                                         VectorNormalize(up);
11578                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11579                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11580                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11581                                         VectorNegate(forward, forward);
11582                                         VectorReflect(forward, 0, up, forward);
11583                                         VectorNormalize(forward);
11584                                         CrossProduct(up, forward, newright);
11585                                         VectorNormalize(newright);
11586                                         // rotate the quad around the up axis vector, this is made
11587                                         // especially easy by the fact we know the quad is flat,
11588                                         // so we only have to subtract the center position and
11589                                         // measure distance along the right vector, and then
11590                                         // multiply that by the newright vector and add back the
11591                                         // center position
11592                                         // we also need to subtract the old position to undo the
11593                                         // displacement from the center, which we do with a
11594                                         // DotProduct, the subtraction/addition of center is also
11595                                         // optimized into DotProducts here
11596                                         l = DotProduct(right, center);
11597                                         for (i = 0;i < 4;i++)
11598                                         {
11599                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11600                                                 f = DotProduct(right, v1) - l;
11601                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.array_batchvertex3f + 3*(j+i));
11602                                         }
11603                                 }
11604                         }
11605                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11606                         rsurface.batchvertex3f_vertexbuffer = NULL;
11607                         rsurface.batchvertex3f_bufferoffset = 0;
11608                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11609                         {
11610                                 Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11611                                 rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11612                                 rsurface.batchnormal3f_vertexbuffer = NULL;
11613                                 rsurface.batchnormal3f_bufferoffset = 0;
11614                         }
11615                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11616                         {
11617                                 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);
11618                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11619                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11620                                 rsurface.batchsvector3f_bufferoffset = 0;
11621                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11622                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11623                                 rsurface.batchtvector3f_bufferoffset = 0;
11624                         }
11625                         break;
11626                 case Q3DEFORM_NORMAL:
11627                         // deform the normals to make reflections wavey
11628                         for (j = 0;j < rsurface.batchnumvertices;j++)
11629                         {
11630                                 float vertex[3];
11631                                 float *normal = rsurface.array_batchnormal3f + 3*j;
11632                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11633                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11634                                 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]);
11635                                 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]);
11636                                 VectorNormalize(normal);
11637                         }
11638                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11639                         rsurface.batchnormal3f_vertexbuffer = NULL;
11640                         rsurface.batchnormal3f_bufferoffset = 0;
11641                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11642                         {
11643                                 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);
11644                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11645                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11646                                 rsurface.batchsvector3f_bufferoffset = 0;
11647                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11648                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11649                                 rsurface.batchtvector3f_bufferoffset = 0;
11650                         }
11651                         break;
11652                 case Q3DEFORM_WAVE:
11653                         // deform vertex array to make wavey water and flags and such
11654                         waveparms[0] = deform->waveparms[0];
11655                         waveparms[1] = deform->waveparms[1];
11656                         waveparms[2] = deform->waveparms[2];
11657                         waveparms[3] = deform->waveparms[3];
11658                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11659                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11660                         // this is how a divisor of vertex influence on deformation
11661                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11662                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11663                         for (j = 0;j < rsurface.batchnumvertices;j++)
11664                         {
11665                                 // if the wavefunc depends on time, evaluate it per-vertex
11666                                 if (waveparms[3])
11667                                 {
11668                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11669                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11670                                 }
11671                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11672                         }
11673                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11674                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11675                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11676                         rsurface.batchvertex3f_vertexbuffer = NULL;
11677                         rsurface.batchvertex3f_bufferoffset = 0;
11678                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11679                         rsurface.batchnormal3f_vertexbuffer = NULL;
11680                         rsurface.batchnormal3f_bufferoffset = 0;
11681                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11682                         {
11683                                 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);
11684                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11685                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11686                                 rsurface.batchsvector3f_bufferoffset = 0;
11687                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11688                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11689                                 rsurface.batchtvector3f_bufferoffset = 0;
11690                         }
11691                         break;
11692                 case Q3DEFORM_BULGE:
11693                         // deform vertex array to make the surface have moving bulges
11694                         for (j = 0;j < rsurface.batchnumvertices;j++)
11695                         {
11696                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11697                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.array_batchvertex3f + 3*j);
11698                         }
11699                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11700                         Mod_BuildNormals(rsurface.batchfirstvertex, rsurface.batchnumvertices, rsurface.batchnumtriangles, rsurface.array_batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.array_batchnormal3f, true);
11701                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11702                         rsurface.batchvertex3f_vertexbuffer = NULL;
11703                         rsurface.batchvertex3f_bufferoffset = 0;
11704                         rsurface.batchnormal3f = rsurface.array_batchnormal3f;
11705                         rsurface.batchnormal3f_vertexbuffer = NULL;
11706                         rsurface.batchnormal3f_bufferoffset = 0;
11707                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11708                         {
11709                                 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);
11710                                 rsurface.batchsvector3f = rsurface.array_batchsvector3f;
11711                                 rsurface.batchsvector3f_vertexbuffer = NULL;
11712                                 rsurface.batchsvector3f_bufferoffset = 0;
11713                                 rsurface.batchtvector3f = rsurface.array_batchtvector3f;
11714                                 rsurface.batchtvector3f_vertexbuffer = NULL;
11715                                 rsurface.batchtvector3f_bufferoffset = 0;
11716                         }
11717                         break;
11718                 case Q3DEFORM_MOVE:
11719                         // deform vertex array
11720                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11721                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11722                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11723                         VectorScale(deform->parms, scale, waveparms);
11724                         for (j = 0;j < rsurface.batchnumvertices;j++)
11725                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.array_batchvertex3f + 3*j);
11726                         rsurface.batchvertex3f = rsurface.array_batchvertex3f;
11727                         rsurface.batchvertex3f_vertexbuffer = NULL;
11728                         rsurface.batchvertex3f_bufferoffset = 0;
11729                         break;
11730                 }
11731         }
11732
11733         // generate texcoords based on the chosen texcoord source
11734         switch(rsurface.texture->tcgen.tcgen)
11735         {
11736         default:
11737         case Q3TCGEN_TEXTURE:
11738                 break;
11739         case Q3TCGEN_LIGHTMAP:
11740                 if (rsurface.batchtexcoordlightmap2f)
11741                         memcpy(rsurface.array_batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, rsurface.batchnumvertices * sizeof(float[2]));
11742                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11743                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11744                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11745                 break;
11746         case Q3TCGEN_VECTOR:
11747                 for (j = 0;j < rsurface.batchnumvertices;j++)
11748                 {
11749                         rsurface.array_batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11750                         rsurface.array_batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11751                 }
11752                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11753                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11754                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11755                 break;
11756         case Q3TCGEN_ENVIRONMENT:
11757                 // make environment reflections using a spheremap
11758                 for (j = 0;j < rsurface.batchnumvertices;j++)
11759                 {
11760                         // identical to Q3A's method, but executed in worldspace so
11761                         // carried models can be shiny too
11762
11763                         float viewer[3], d, reflected[3], worldreflected[3];
11764
11765                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11766                         // VectorNormalize(viewer);
11767
11768                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11769
11770                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11771                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11772                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11773                         // note: this is proportinal to viewer, so we can normalize later
11774
11775                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11776                         VectorNormalize(worldreflected);
11777
11778                         // note: this sphere map only uses world x and z!
11779                         // so positive and negative y will LOOK THE SAME.
11780                         rsurface.array_batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11781                         rsurface.array_batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11782                 }
11783                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11784                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11785                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11786                 break;
11787         }
11788         // the only tcmod that needs software vertex processing is turbulent, so
11789         // check for it here and apply the changes if needed
11790         // and we only support that as the first one
11791         // (handling a mixture of turbulent and other tcmods would be problematic
11792         //  without punting it entirely to a software path)
11793         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11794         {
11795                 amplitude = rsurface.texture->tcmods[0].parms[1];
11796                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11797                 for (j = 0;j < rsurface.batchnumvertices;j++)
11798                 {
11799                         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);
11800                         rsurface.array_batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11801                 }
11802                 rsurface.batchtexcoordtexture2f = rsurface.array_batchtexcoordtexture2f;
11803                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11804                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11805         }
11806
11807         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11808         {
11809                 // convert the modified arrays to vertex structs
11810                 rsurface.batchvertexmesh = rsurface.array_batchvertexmesh;
11811                 rsurface.batchvertexmeshbuffer = NULL;
11812                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11813                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11814                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11815                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11816                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11817                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11818                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11819                 {
11820                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11821                         {
11822                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11823                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11824                         }
11825                 }
11826                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11827                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11828                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11829                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11830                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11831                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11832                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11833                         for (j = 0, vertexmesh = rsurface.array_batchvertexmesh;j < rsurface.batchnumvertices;j++, vertexmesh++)
11834                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11835         }
11836
11837         if (needsupdate & batchneed & BATCHNEED_VERTEXPOSITION)
11838         {
11839                 // convert the modified arrays to vertex structs
11840                 rsurface.batchvertexposition = rsurface.array_batchvertexposition;
11841                 rsurface.batchvertexpositionbuffer = NULL;
11842                 if (sizeof(r_vertexposition_t) == sizeof(float[3]))
11843                         memcpy(rsurface.array_batchvertexposition, rsurface.batchvertex3f, rsurface.batchnumvertices * sizeof(r_vertexposition_t));
11844                 else
11845                         for (j = 0, vertexposition = rsurface.array_batchvertexposition;j < rsurface.batchnumvertices;j++, vertexposition++)
11846                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexposition->vertex3f);
11847         }
11848 }
11849
11850 void RSurf_DrawBatch(void)
11851 {
11852         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);
11853 }
11854
11855 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11856 {
11857         // pick the closest matching water plane
11858         int planeindex, vertexindex, bestplaneindex = -1;
11859         float d, bestd;
11860         vec3_t vert;
11861         const float *v;
11862         r_waterstate_waterplane_t *p;
11863         bestd = 0;
11864         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11865         {
11866                 if(p->camera_entity != rsurface.texture->camera_entity)
11867                         continue;
11868                 d = 0;
11869                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
11870                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11871                 {
11872                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11873                         d += fabs(PlaneDiff(vert, &p->plane));
11874                 }
11875                 if (bestd > d || bestplaneindex < 0)
11876                 {
11877                         bestd = d;
11878                         bestplaneindex = planeindex;
11879                 }
11880         }
11881         return bestplaneindex;
11882 }
11883
11884 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11885 {
11886         int i;
11887         for (i = 0;i < rsurface.batchnumvertices;i++)
11888                 Vector4Set(rsurface.array_passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11889         rsurface.passcolor4f = rsurface.array_passcolor4f;
11890         rsurface.passcolor4f_vertexbuffer = 0;
11891         rsurface.passcolor4f_bufferoffset = 0;
11892 }
11893
11894 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11895 {
11896         int i;
11897         float f;
11898         const float *v;
11899         const float *c;
11900         float *c2;
11901         if (rsurface.passcolor4f)
11902         {
11903                 // generate color arrays
11904                 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)
11905                 {
11906                         f = RSurf_FogVertex(v);
11907                         c2[0] = c[0] * f;
11908                         c2[1] = c[1] * f;
11909                         c2[2] = c[2] * f;
11910                         c2[3] = c[3];
11911                 }
11912         }
11913         else
11914         {
11915                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11916                 {
11917                         f = RSurf_FogVertex(v);
11918                         c2[0] = f;
11919                         c2[1] = f;
11920                         c2[2] = f;
11921                         c2[3] = 1;
11922                 }
11923         }
11924         rsurface.passcolor4f = rsurface.array_passcolor4f;
11925         rsurface.passcolor4f_vertexbuffer = 0;
11926         rsurface.passcolor4f_bufferoffset = 0;
11927 }
11928
11929 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11930 {
11931         int i;
11932         float f;
11933         const float *v;
11934         const float *c;
11935         float *c2;
11936         if (!rsurface.passcolor4f)
11937                 return;
11938         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)
11939         {
11940                 f = RSurf_FogVertex(v);
11941                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11942                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11943                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11944                 c2[3] = c[3];
11945         }
11946         rsurface.passcolor4f = rsurface.array_passcolor4f;
11947         rsurface.passcolor4f_vertexbuffer = 0;
11948         rsurface.passcolor4f_bufferoffset = 0;
11949 }
11950
11951 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11952 {
11953         int i;
11954         const float *c;
11955         float *c2;
11956         if (!rsurface.passcolor4f)
11957                 return;
11958         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11959         {
11960                 c2[0] = c[0] * r;
11961                 c2[1] = c[1] * g;
11962                 c2[2] = c[2] * b;
11963                 c2[3] = c[3] * a;
11964         }
11965         rsurface.passcolor4f = rsurface.array_passcolor4f;
11966         rsurface.passcolor4f_vertexbuffer = 0;
11967         rsurface.passcolor4f_bufferoffset = 0;
11968 }
11969
11970 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11971 {
11972         int i;
11973         const float *c;
11974         float *c2;
11975         if (!rsurface.passcolor4f)
11976                 return;
11977         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11978         {
11979                 c2[0] = c[0] + r_refdef.scene.ambient;
11980                 c2[1] = c[1] + r_refdef.scene.ambient;
11981                 c2[2] = c[2] + r_refdef.scene.ambient;
11982                 c2[3] = c[3];
11983         }
11984         rsurface.passcolor4f = rsurface.array_passcolor4f;
11985         rsurface.passcolor4f_vertexbuffer = 0;
11986         rsurface.passcolor4f_bufferoffset = 0;
11987 }
11988
11989 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11990 {
11991         // TODO: optimize
11992         rsurface.passcolor4f = NULL;
11993         rsurface.passcolor4f_vertexbuffer = 0;
11994         rsurface.passcolor4f_bufferoffset = 0;
11995         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11996         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11997         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11998         GL_Color(r, g, b, a);
11999         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12000         RSurf_DrawBatch();
12001 }
12002
12003 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12004 {
12005         // TODO: optimize applyfog && applycolor case
12006         // just apply fog if necessary, and tint the fog color array if necessary
12007         rsurface.passcolor4f = NULL;
12008         rsurface.passcolor4f_vertexbuffer = 0;
12009         rsurface.passcolor4f_bufferoffset = 0;
12010         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12011         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12012         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12013         GL_Color(r, g, b, a);
12014         RSurf_DrawBatch();
12015 }
12016
12017 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12018 {
12019         // TODO: optimize
12020         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12021         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12022         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12023         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12024         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12025         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12026         GL_Color(r, g, b, a);
12027         RSurf_DrawBatch();
12028 }
12029
12030 static void RSurf_DrawBatch_GL11_ClampColor(void)
12031 {
12032         int i;
12033         const float *c1;
12034         float *c2;
12035         if (!rsurface.passcolor4f)
12036                 return;
12037         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.array_passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12038         {
12039                 c2[0] = bound(0.0f, c1[0], 1.0f);
12040                 c2[1] = bound(0.0f, c1[1], 1.0f);
12041                 c2[2] = bound(0.0f, c1[2], 1.0f);
12042                 c2[3] = bound(0.0f, c1[3], 1.0f);
12043         }
12044 }
12045
12046 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12047 {
12048         int i;
12049         float f;
12050         float alpha;
12051         const float *v;
12052         const float *n;
12053         float *c;
12054         vec3_t ambientcolor;
12055         vec3_t diffusecolor;
12056         vec3_t lightdir;
12057         // TODO: optimize
12058         // model lighting
12059         VectorCopy(rsurface.modellight_lightdir, lightdir);
12060         f = 0.5f * r_refdef.lightmapintensity;
12061         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12062         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12063         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12064         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12065         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12066         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12067         alpha = *a;
12068         if (VectorLength2(diffusecolor) > 0)
12069         {
12070                 // q3-style directional shading
12071                 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)
12072                 {
12073                         if ((f = DotProduct(n, lightdir)) > 0)
12074                                 VectorMA(ambientcolor, f, diffusecolor, c);
12075                         else
12076                                 VectorCopy(ambientcolor, c);
12077                         c[3] = alpha;
12078                 }
12079                 *r = 1;
12080                 *g = 1;
12081                 *b = 1;
12082                 *a = 1;
12083                 rsurface.passcolor4f = rsurface.array_passcolor4f;
12084                 rsurface.passcolor4f_vertexbuffer = 0;
12085                 rsurface.passcolor4f_bufferoffset = 0;
12086                 *applycolor = false;
12087         }
12088         else
12089         {
12090                 *r = ambientcolor[0];
12091                 *g = ambientcolor[1];
12092                 *b = ambientcolor[2];
12093                 rsurface.passcolor4f = NULL;
12094                 rsurface.passcolor4f_vertexbuffer = 0;
12095                 rsurface.passcolor4f_bufferoffset = 0;
12096         }
12097 }
12098
12099 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12100 {
12101         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12102         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12103         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12104         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12105         GL_Color(r, g, b, a);
12106         RSurf_DrawBatch();
12107 }
12108
12109 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12110 {
12111         int i;
12112         float f;
12113         const float *v;
12114         float *c;
12115         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.array_passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12116         {
12117                 f = 1 - RSurf_FogVertex(v);
12118                 c[0] = r;
12119                 c[1] = g;
12120                 c[2] = b;
12121                 c[3] = f * a;
12122         }
12123 }
12124
12125 void RSurf_SetupDepthAndCulling(void)
12126 {
12127         // submodels are biased to avoid z-fighting with world surfaces that they
12128         // may be exactly overlapping (avoids z-fighting artifacts on certain
12129         // doors and things in Quake maps)
12130         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12131         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12132         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12133         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12134 }
12135
12136 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12137 {
12138         // transparent sky would be ridiculous
12139         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12140                 return;
12141         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12142         skyrenderlater = true;
12143         RSurf_SetupDepthAndCulling();
12144         GL_DepthMask(true);
12145         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12146         // skymasking on them, and Quake3 never did sky masking (unlike
12147         // software Quake and software Quake2), so disable the sky masking
12148         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12149         // and skymasking also looks very bad when noclipping outside the
12150         // level, so don't use it then either.
12151         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12152         {
12153                 R_Mesh_ResetTextureState();
12154                 if (skyrendermasked)
12155                 {
12156                         R_SetupShader_DepthOrShadow();
12157                         // depth-only (masking)
12158                         GL_ColorMask(0,0,0,0);
12159                         // just to make sure that braindead drivers don't draw
12160                         // anything despite that colormask...
12161                         GL_BlendFunc(GL_ZERO, GL_ONE);
12162                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12163                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12164                 }
12165                 else
12166                 {
12167                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12168                         // fog sky
12169                         GL_BlendFunc(GL_ONE, GL_ZERO);
12170                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12171                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12172                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12173                 }
12174                 RSurf_DrawBatch();
12175                 if (skyrendermasked)
12176                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12177         }
12178         R_Mesh_ResetTextureState();
12179         GL_Color(1, 1, 1, 1);
12180 }
12181
12182 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12183 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12184 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12185 {
12186         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12187                 return;
12188         if (prepass)
12189         {
12190                 // render screenspace normalmap to texture
12191                 GL_DepthMask(true);
12192                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12193                 RSurf_DrawBatch();
12194                 return;
12195         }
12196
12197         // bind lightmap texture
12198
12199         // water/refraction/reflection/camera surfaces have to be handled specially
12200         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)) && !r_waterstate.renderingscene)
12201         {
12202                 int start, end, startplaneindex;
12203                 for (start = 0;start < texturenumsurfaces;start = end)
12204                 {
12205                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12206                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12207                                 ;
12208                         // now that we have a batch using the same planeindex, render it
12209                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)) && !r_waterstate.renderingscene)
12210                         {
12211                                 // render water or distortion background
12212                                 GL_DepthMask(true);
12213                                 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));
12214                                 RSurf_DrawBatch();
12215                                 // blend surface on top
12216                                 GL_DepthMask(false);
12217                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12218                                 RSurf_DrawBatch();
12219                         }
12220                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION) && !r_waterstate.renderingscene)
12221                         {
12222                                 // render surface with reflection texture as input
12223                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12224                                 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));
12225                                 RSurf_DrawBatch();
12226                         }
12227                 }
12228                 return;
12229         }
12230
12231         // render surface batch normally
12232         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12233         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12234         RSurf_DrawBatch();
12235 }
12236
12237 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12238 {
12239         // OpenGL 1.3 path - anything not completely ancient
12240         qboolean applycolor;
12241         qboolean applyfog;
12242         int layerindex;
12243         const texturelayer_t *layer;
12244         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);
12245         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12246
12247         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12248         {
12249                 vec4_t layercolor;
12250                 int layertexrgbscale;
12251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12252                 {
12253                         if (layerindex == 0)
12254                                 GL_AlphaTest(true);
12255                         else
12256                         {
12257                                 GL_AlphaTest(false);
12258                                 GL_DepthFunc(GL_EQUAL);
12259                         }
12260                 }
12261                 GL_DepthMask(layer->depthmask && writedepth);
12262                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12263                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12264                 {
12265                         layertexrgbscale = 4;
12266                         VectorScale(layer->color, 0.25f, layercolor);
12267                 }
12268                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12269                 {
12270                         layertexrgbscale = 2;
12271                         VectorScale(layer->color, 0.5f, layercolor);
12272                 }
12273                 else
12274                 {
12275                         layertexrgbscale = 1;
12276                         VectorScale(layer->color, 1.0f, layercolor);
12277                 }
12278                 layercolor[3] = layer->color[3];
12279                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12280                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12281                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12282                 switch (layer->type)
12283                 {
12284                 case TEXTURELAYERTYPE_LITTEXTURE:
12285                         // single-pass lightmapped texture with 2x rgbscale
12286                         R_Mesh_TexBind(0, r_texture_white);
12287                         R_Mesh_TexMatrix(0, NULL);
12288                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12289                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12290                         R_Mesh_TexBind(1, layer->texture);
12291                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12292                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12293                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12294                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12295                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12296                         else if (rsurface.uselightmaptexture)
12297                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12298                         else
12299                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12300                         break;
12301                 case TEXTURELAYERTYPE_TEXTURE:
12302                         // singletexture unlit texture with transparency support
12303                         R_Mesh_TexBind(0, layer->texture);
12304                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12305                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12306                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12307                         R_Mesh_TexBind(1, 0);
12308                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12309                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12310                         break;
12311                 case TEXTURELAYERTYPE_FOG:
12312                         // singletexture fogging
12313                         if (layer->texture)
12314                         {
12315                                 R_Mesh_TexBind(0, layer->texture);
12316                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12317                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12318                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12319                         }
12320                         else
12321                         {
12322                                 R_Mesh_TexBind(0, 0);
12323                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12324                         }
12325                         R_Mesh_TexBind(1, 0);
12326                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12327                         // generate a color array for the fog pass
12328                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12329                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12330                         RSurf_DrawBatch();
12331                         break;
12332                 default:
12333                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12334                 }
12335         }
12336         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12337         {
12338                 GL_DepthFunc(GL_LEQUAL);
12339                 GL_AlphaTest(false);
12340         }
12341 }
12342
12343 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12344 {
12345         // OpenGL 1.1 - crusty old voodoo path
12346         qboolean applyfog;
12347         int layerindex;
12348         const texturelayer_t *layer;
12349         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);
12350         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12351
12352         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12353         {
12354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12355                 {
12356                         if (layerindex == 0)
12357                                 GL_AlphaTest(true);
12358                         else
12359                         {
12360                                 GL_AlphaTest(false);
12361                                 GL_DepthFunc(GL_EQUAL);
12362                         }
12363                 }
12364                 GL_DepthMask(layer->depthmask && writedepth);
12365                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12366                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12367                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12368                 switch (layer->type)
12369                 {
12370                 case TEXTURELAYERTYPE_LITTEXTURE:
12371                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12372                         {
12373                                 // two-pass lit texture with 2x rgbscale
12374                                 // first the lightmap pass
12375                                 R_Mesh_TexBind(0, r_texture_white);
12376                                 R_Mesh_TexMatrix(0, NULL);
12377                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12378                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12379                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12380                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12381                                 else if (rsurface.uselightmaptexture)
12382                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12383                                 else
12384                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12385                                 // then apply the texture to it
12386                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12387                                 R_Mesh_TexBind(0, layer->texture);
12388                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12389                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12390                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12391                                 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);
12392                         }
12393                         else
12394                         {
12395                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12396                                 R_Mesh_TexBind(0, layer->texture);
12397                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12398                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12399                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12400                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12401                                         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);
12402                                 else
12403                                         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);
12404                         }
12405                         break;
12406                 case TEXTURELAYERTYPE_TEXTURE:
12407                         // singletexture unlit texture with transparency support
12408                         R_Mesh_TexBind(0, layer->texture);
12409                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12410                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12411                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12412                         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);
12413                         break;
12414                 case TEXTURELAYERTYPE_FOG:
12415                         // singletexture fogging
12416                         if (layer->texture)
12417                         {
12418                                 R_Mesh_TexBind(0, layer->texture);
12419                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12420                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12421                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12422                         }
12423                         else
12424                         {
12425                                 R_Mesh_TexBind(0, 0);
12426                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12427                         }
12428                         // generate a color array for the fog pass
12429                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.array_passcolor4f, 0, 0);
12430                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12431                         RSurf_DrawBatch();
12432                         break;
12433                 default:
12434                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12435                 }
12436         }
12437         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12438         {
12439                 GL_DepthFunc(GL_LEQUAL);
12440                 GL_AlphaTest(false);
12441         }
12442 }
12443
12444 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12445 {
12446         int vi;
12447         int j;
12448         r_vertexgeneric_t *batchvertex;
12449         float c[4];
12450
12451         GL_AlphaTest(false);
12452         R_Mesh_ResetTextureState();
12453         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12454
12455         if(rsurface.texture && rsurface.texture->currentskinframe)
12456         {
12457                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12458                 c[3] *= rsurface.texture->currentalpha;
12459         }
12460         else
12461         {
12462                 c[0] = 1;
12463                 c[1] = 0;
12464                 c[2] = 1;
12465                 c[3] = 1;
12466         }
12467
12468         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12469         {
12470                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12471                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12472                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12473         }
12474
12475         // brighten it up (as texture value 127 means "unlit")
12476         c[0] *= 2 * r_refdef.view.colorscale;
12477         c[1] *= 2 * r_refdef.view.colorscale;
12478         c[2] *= 2 * r_refdef.view.colorscale;
12479
12480         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12481                 c[3] *= r_wateralpha.value;
12482
12483         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12484         {
12485                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12486                 GL_DepthMask(false);
12487         }
12488         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12489         {
12490                 GL_BlendFunc(GL_ONE, GL_ONE);
12491                 GL_DepthMask(false);
12492         }
12493         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12494         {
12495                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12496                 GL_DepthMask(false);
12497         }
12498         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12499         {
12500                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12501                 GL_DepthMask(false);
12502         }
12503         else
12504         {
12505                 GL_BlendFunc(GL_ONE, GL_ZERO);
12506                 GL_DepthMask(writedepth);
12507         }
12508
12509         if (r_showsurfaces.integer == 3)
12510         {
12511                 rsurface.passcolor4f = NULL;
12512
12513                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12514                 {
12515                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12516
12517                         rsurface.passcolor4f = NULL;
12518                         rsurface.passcolor4f_vertexbuffer = 0;
12519                         rsurface.passcolor4f_bufferoffset = 0;
12520                 }
12521                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12522                 {
12523                         qboolean applycolor = true;
12524                         float one = 1.0;
12525
12526                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12527
12528                         r_refdef.lightmapintensity = 1;
12529                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12530                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12531                 }
12532                 else
12533                 {
12534                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12535
12536                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12537                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12538                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12539                 }
12540
12541                 if(!rsurface.passcolor4f)
12542                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12543
12544                 RSurf_DrawBatch_GL11_ApplyAmbient();
12545                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12546                 if(r_refdef.fogenabled)
12547                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12548                 RSurf_DrawBatch_GL11_ClampColor();
12549
12550                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12551                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12552                 RSurf_DrawBatch();
12553         }
12554         else if (!r_refdef.view.showdebug)
12555         {
12556                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12557                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12558                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12559                 {
12560                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12561                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12562                 }
12563                 R_Mesh_PrepareVertices_Generic_Unlock();
12564                 RSurf_DrawBatch();
12565         }
12566         else if (r_showsurfaces.integer == 4)
12567         {
12568                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12569                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12570                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12571                 {
12572                         unsigned char c = vi << 3;
12573                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12574                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12575                 }
12576                 R_Mesh_PrepareVertices_Generic_Unlock();
12577                 RSurf_DrawBatch();
12578         }
12579         else if (r_showsurfaces.integer == 2)
12580         {
12581                 const int *e;
12582                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12583                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12584                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12585                 {
12586                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12587                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12588                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12589                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12590                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12591                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12592                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12593                 }
12594                 R_Mesh_PrepareVertices_Generic_Unlock();
12595                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12596         }
12597         else
12598         {
12599                 int texturesurfaceindex;
12600                 int k;
12601                 const msurface_t *surface;
12602                 unsigned char surfacecolor4ub[4];
12603                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12604                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12605                 vi = 0;
12606                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12607                 {
12608                         surface = texturesurfacelist[texturesurfaceindex];
12609                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12610                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12611                         for (j = 0;j < surface->num_vertices;j++)
12612                         {
12613                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12614                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12615                                 vi++;
12616                         }
12617                 }
12618                 R_Mesh_PrepareVertices_Generic_Unlock();
12619                 RSurf_DrawBatch();
12620         }
12621 }
12622
12623 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12624 {
12625         CHECKGLERROR
12626         RSurf_SetupDepthAndCulling();
12627         if (r_showsurfaces.integer)
12628         {
12629                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12630                 return;
12631         }
12632         switch (vid.renderpath)
12633         {
12634         case RENDERPATH_GL20:
12635         case RENDERPATH_CGGL:
12636         case RENDERPATH_D3D9:
12637         case RENDERPATH_D3D10:
12638         case RENDERPATH_D3D11:
12639                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12640                 break;
12641         case RENDERPATH_GL13:
12642                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12643                 break;
12644         case RENDERPATH_GL11:
12645                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12646                 break;
12647         }
12648         CHECKGLERROR
12649 }
12650
12651 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12652 {
12653         CHECKGLERROR
12654         RSurf_SetupDepthAndCulling();
12655         if (r_showsurfaces.integer)
12656         {
12657                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12658                 return;
12659         }
12660         switch (vid.renderpath)
12661         {
12662         case RENDERPATH_GL20:
12663         case RENDERPATH_CGGL:
12664         case RENDERPATH_D3D9:
12665         case RENDERPATH_D3D10:
12666         case RENDERPATH_D3D11:
12667                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12668                 break;
12669         case RENDERPATH_GL13:
12670                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12671                 break;
12672         case RENDERPATH_GL11:
12673                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12674                 break;
12675         }
12676         CHECKGLERROR
12677 }
12678
12679 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12680 {
12681         int i, j;
12682         int texturenumsurfaces, endsurface;
12683         texture_t *texture;
12684         const msurface_t *surface;
12685 #define MAXBATCH_TRANSPARENTSURFACES 256
12686         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12687
12688         // if the model is static it doesn't matter what value we give for
12689         // wantnormals and wanttangents, so this logic uses only rules applicable
12690         // to a model, knowing that they are meaningless otherwise
12691         if (ent == r_refdef.scene.worldentity)
12692                 RSurf_ActiveWorldEntity();
12693         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12694                 RSurf_ActiveModelEntity(ent, false, false, false);
12695         else
12696         {
12697                 switch (vid.renderpath)
12698                 {
12699                 case RENDERPATH_GL20:
12700                 case RENDERPATH_CGGL:
12701                 case RENDERPATH_D3D9:
12702                 case RENDERPATH_D3D10:
12703                 case RENDERPATH_D3D11:
12704                         RSurf_ActiveModelEntity(ent, true, true, false);
12705                         break;
12706                 case RENDERPATH_GL13:
12707                 case RENDERPATH_GL11:
12708                         RSurf_ActiveModelEntity(ent, true, false, false);
12709                         break;
12710                 }
12711         }
12712
12713         if (r_transparentdepthmasking.integer)
12714         {
12715                 qboolean setup = false;
12716                 for (i = 0;i < numsurfaces;i = j)
12717                 {
12718                         j = i + 1;
12719                         surface = rsurface.modelsurfaces + surfacelist[i];
12720                         texture = surface->texture;
12721                         rsurface.texture = R_GetCurrentTexture(texture);
12722                         rsurface.lightmaptexture = NULL;
12723                         rsurface.deluxemaptexture = NULL;
12724                         rsurface.uselightmaptexture = false;
12725                         // scan ahead until we find a different texture
12726                         endsurface = min(i + 1024, numsurfaces);
12727                         texturenumsurfaces = 0;
12728                         texturesurfacelist[texturenumsurfaces++] = surface;
12729                         for (;j < endsurface;j++)
12730                         {
12731                                 surface = rsurface.modelsurfaces + surfacelist[j];
12732                                 if (texture != surface->texture)
12733                                         break;
12734                                 texturesurfacelist[texturenumsurfaces++] = surface;
12735                         }
12736                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12737                                 continue;
12738                         // render the range of surfaces as depth
12739                         if (!setup)
12740                         {
12741                                 setup = true;
12742                                 GL_ColorMask(0,0,0,0);
12743                                 GL_Color(1,1,1,1);
12744                                 GL_DepthTest(true);
12745                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12746                                 GL_DepthMask(true);
12747                                 GL_AlphaTest(false);
12748                                 R_Mesh_ResetTextureState();
12749                                 R_SetupShader_DepthOrShadow();
12750                         }
12751                         RSurf_SetupDepthAndCulling();
12752                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12753                         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12754                         RSurf_DrawBatch();
12755                 }
12756                 if (setup)
12757                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12758         }
12759
12760         for (i = 0;i < numsurfaces;i = j)
12761         {
12762                 j = i + 1;
12763                 surface = rsurface.modelsurfaces + surfacelist[i];
12764                 texture = surface->texture;
12765                 rsurface.texture = R_GetCurrentTexture(texture);
12766                 rsurface.lightmaptexture = surface->lightmaptexture;
12767                 rsurface.deluxemaptexture = surface->deluxemaptexture;
12768                 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12769                 // scan ahead until we find a different texture
12770                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12771                 texturenumsurfaces = 0;
12772                 texturesurfacelist[texturenumsurfaces++] = surface;
12773                 for (;j < endsurface;j++)
12774                 {
12775                         surface = rsurface.modelsurfaces + surfacelist[j];
12776                         if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12777                                 break;
12778                         texturesurfacelist[texturenumsurfaces++] = surface;
12779                 }
12780                 // render the range of surfaces
12781                 if (ent == r_refdef.scene.worldentity)
12782                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12783                 else
12784                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12785         }
12786         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12787         GL_AlphaTest(false);
12788 }
12789
12790 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12791 {
12792         // transparent surfaces get pushed off into the transparent queue
12793         int surfacelistindex;
12794         const msurface_t *surface;
12795         vec3_t tempcenter, center;
12796         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12797         {
12798                 surface = texturesurfacelist[surfacelistindex];
12799                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12800                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12801                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12802                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12803                 if (queueentity->transparent_offset) // transparent offset
12804                 {
12805                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12806                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12807                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12808                 }
12809                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12810         }
12811 }
12812
12813 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12814 {
12815         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12816                 return;
12817         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12818                 return;
12819         RSurf_SetupDepthAndCulling();
12820         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXPOSITION, texturenumsurfaces, texturesurfacelist);
12821         R_Mesh_PrepareVertices_Position(rsurface.batchnumvertices, rsurface.batchvertexposition, rsurface.batchvertexpositionbuffer);
12822         RSurf_DrawBatch();
12823 }
12824
12825 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12826 {
12827         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12828         CHECKGLERROR
12829         if (depthonly)
12830                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12831         else if (prepass)
12832         {
12833                 if (!rsurface.texture->currentnumlayers)
12834                         return;
12835                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12836                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12837                 else
12838                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12839         }
12840         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12841                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12842         else if (!rsurface.texture->currentnumlayers)
12843                 return;
12844         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12845         {
12846                 // in the deferred case, transparent surfaces were queued during prepass
12847                 if (!r_shadow_usingdeferredprepass)
12848                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12849         }
12850         else
12851         {
12852                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12853                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12854         }
12855         CHECKGLERROR
12856 }
12857
12858 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12859 {
12860         int i, j;
12861         texture_t *texture;
12862         // break the surface list down into batches by texture and use of lightmapping
12863         for (i = 0;i < numsurfaces;i = j)
12864         {
12865                 j = i + 1;
12866                 // texture is the base texture pointer, rsurface.texture is the
12867                 // current frame/skin the texture is directing us to use (for example
12868                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12869                 // use skin 1 instead)
12870                 texture = surfacelist[i]->texture;
12871                 rsurface.texture = R_GetCurrentTexture(texture);
12872                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12873                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12874                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12875                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12876                 {
12877                         // if this texture is not the kind we want, skip ahead to the next one
12878                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12879                                 ;
12880                         continue;
12881                 }
12882                 // simply scan ahead until we find a different texture or lightmap state
12883                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12884                         ;
12885                 // render the range of surfaces
12886                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12887         }
12888 }
12889
12890 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12891 {
12892         CHECKGLERROR
12893         if (depthonly)
12894                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12895         else if (prepass)
12896         {
12897                 if (!rsurface.texture->currentnumlayers)
12898                         return;
12899                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12900                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12901                 else
12902                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12903         }
12904         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12905                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12906         else if (!rsurface.texture->currentnumlayers)
12907                 return;
12908         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12909         {
12910                 // in the deferred case, transparent surfaces were queued during prepass
12911                 if (!r_shadow_usingdeferredprepass)
12912                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12913         }
12914         else
12915         {
12916                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12917                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12918         }
12919         CHECKGLERROR
12920 }
12921
12922 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12923 {
12924         int i, j;
12925         texture_t *texture;
12926         // break the surface list down into batches by texture and use of lightmapping
12927         for (i = 0;i < numsurfaces;i = j)
12928         {
12929                 j = i + 1;
12930                 // texture is the base texture pointer, rsurface.texture is the
12931                 // current frame/skin the texture is directing us to use (for example
12932                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12933                 // use skin 1 instead)
12934                 texture = surfacelist[i]->texture;
12935                 rsurface.texture = R_GetCurrentTexture(texture);
12936                 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12937                 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12938                 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL && !depthonly && !prepass;
12939                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12940                 {
12941                         // if this texture is not the kind we want, skip ahead to the next one
12942                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12943                                 ;
12944                         continue;
12945                 }
12946                 // simply scan ahead until we find a different texture or lightmap state
12947                 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12948                         ;
12949                 // render the range of surfaces
12950                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12951         }
12952 }
12953
12954 float locboxvertex3f[6*4*3] =
12955 {
12956         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12957         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12958         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12959         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12960         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12961         1,0,0, 0,0,0, 0,1,0, 1,1,0
12962 };
12963
12964 unsigned short locboxelements[6*2*3] =
12965 {
12966          0, 1, 2, 0, 2, 3,
12967          4, 5, 6, 4, 6, 7,
12968          8, 9,10, 8,10,11,
12969         12,13,14, 12,14,15,
12970         16,17,18, 16,18,19,
12971         20,21,22, 20,22,23
12972 };
12973
12974 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12975 {
12976         int i, j;
12977         cl_locnode_t *loc = (cl_locnode_t *)ent;
12978         vec3_t mins, size;
12979         float vertex3f[6*4*3];
12980         CHECKGLERROR
12981         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12982         GL_DepthMask(false);
12983         GL_DepthRange(0, 1);
12984         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12985         GL_DepthTest(true);
12986         GL_CullFace(GL_NONE);
12987         R_EntityMatrix(&identitymatrix);
12988
12989         R_Mesh_ResetTextureState();
12990
12991         i = surfacelist[0];
12992         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12993                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12994                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12995                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12996
12997         if (VectorCompare(loc->mins, loc->maxs))
12998         {
12999                 VectorSet(size, 2, 2, 2);
13000                 VectorMA(loc->mins, -0.5f, size, mins);
13001         }
13002         else
13003         {
13004                 VectorCopy(loc->mins, mins);
13005                 VectorSubtract(loc->maxs, loc->mins, size);
13006         }
13007
13008         for (i = 0;i < 6*4*3;)
13009                 for (j = 0;j < 3;j++, i++)
13010                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13011
13012         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13013         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13014         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13015 }
13016
13017 void R_DrawLocs(void)
13018 {
13019         int index;
13020         cl_locnode_t *loc, *nearestloc;
13021         vec3_t center;
13022         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13023         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13024         {
13025                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13026                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13027         }
13028 }
13029
13030 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13031 {
13032         if (decalsystem->decals)
13033                 Mem_Free(decalsystem->decals);
13034         memset(decalsystem, 0, sizeof(*decalsystem));
13035 }
13036
13037 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)
13038 {
13039         tridecal_t *decal;
13040         tridecal_t *decals;
13041         int i;
13042
13043         // expand or initialize the system
13044         if (decalsystem->maxdecals <= decalsystem->numdecals)
13045         {
13046                 decalsystem_t old = *decalsystem;
13047                 qboolean useshortelements;
13048                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13049                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13050                 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)));
13051                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13052                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13053                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13054                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13055                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13056                 if (decalsystem->numdecals)
13057                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13058                 if (old.decals)
13059                         Mem_Free(old.decals);
13060                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13061                         decalsystem->element3i[i] = i;
13062                 if (useshortelements)
13063                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13064                                 decalsystem->element3s[i] = i;
13065         }
13066
13067         // grab a decal and search for another free slot for the next one
13068         decals = decalsystem->decals;
13069         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13070         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13071                 ;
13072         decalsystem->freedecal = i;
13073         if (decalsystem->numdecals <= i)
13074                 decalsystem->numdecals = i + 1;
13075
13076         // initialize the decal
13077         decal->lived = 0;
13078         decal->triangleindex = triangleindex;
13079         decal->surfaceindex = surfaceindex;
13080         decal->decalsequence = decalsequence;
13081         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13082         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13083         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13084         decal->color4ub[0][3] = 255;
13085         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13086         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13087         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13088         decal->color4ub[1][3] = 255;
13089         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13090         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13091         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13092         decal->color4ub[2][3] = 255;
13093         decal->vertex3f[0][0] = v0[0];
13094         decal->vertex3f[0][1] = v0[1];
13095         decal->vertex3f[0][2] = v0[2];
13096         decal->vertex3f[1][0] = v1[0];
13097         decal->vertex3f[1][1] = v1[1];
13098         decal->vertex3f[1][2] = v1[2];
13099         decal->vertex3f[2][0] = v2[0];
13100         decal->vertex3f[2][1] = v2[1];
13101         decal->vertex3f[2][2] = v2[2];
13102         decal->texcoord2f[0][0] = t0[0];
13103         decal->texcoord2f[0][1] = t0[1];
13104         decal->texcoord2f[1][0] = t1[0];
13105         decal->texcoord2f[1][1] = t1[1];
13106         decal->texcoord2f[2][0] = t2[0];
13107         decal->texcoord2f[2][1] = t2[1];
13108 }
13109
13110 extern cvar_t cl_decals_bias;
13111 extern cvar_t cl_decals_models;
13112 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13113 // baseparms, parms, temps
13114 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)
13115 {
13116         int cornerindex;
13117         int index;
13118         float v[9][3];
13119         const float *vertex3f;
13120         int numpoints;
13121         float points[2][9][3];
13122         float temp[3];
13123         float tc[9][2];
13124         float f;
13125         float c[9][4];
13126         const int *e;
13127
13128         e = rsurface.modelelement3i + 3*triangleindex;
13129
13130         vertex3f = rsurface.modelvertex3f;
13131
13132         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13133         {
13134                 index = 3*e[cornerindex];
13135                 VectorCopy(vertex3f + index, v[cornerindex]);
13136         }
13137         // cull backfaces
13138         //TriangleNormal(v[0], v[1], v[2], normal);
13139         //if (DotProduct(normal, localnormal) < 0.0f)
13140         //      continue;
13141         // clip by each of the box planes formed from the projection matrix
13142         // if anything survives, we emit the decal
13143         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]);
13144         if (numpoints < 3)
13145                 return;
13146         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]);
13147         if (numpoints < 3)
13148                 return;
13149         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]);
13150         if (numpoints < 3)
13151                 return;
13152         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]);
13153         if (numpoints < 3)
13154                 return;
13155         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]);
13156         if (numpoints < 3)
13157                 return;
13158         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]);
13159         if (numpoints < 3)
13160                 return;
13161         // some part of the triangle survived, so we have to accept it...
13162         if (dynamic)
13163         {
13164                 // dynamic always uses the original triangle
13165                 numpoints = 3;
13166                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13167                 {
13168                         index = 3*e[cornerindex];
13169                         VectorCopy(vertex3f + index, v[cornerindex]);
13170                 }
13171         }
13172         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13173         {
13174                 // convert vertex positions to texcoords
13175                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13176                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13177                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13178                 // calculate distance fade from the projection origin
13179                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13180                 f = bound(0.0f, f, 1.0f);
13181                 c[cornerindex][0] = r * f;
13182                 c[cornerindex][1] = g * f;
13183                 c[cornerindex][2] = b * f;
13184                 c[cornerindex][3] = 1.0f;
13185                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13186         }
13187         if (dynamic)
13188                 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);
13189         else
13190                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13191                         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);
13192 }
13193 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)
13194 {
13195         matrix4x4_t projection;
13196         decalsystem_t *decalsystem;
13197         qboolean dynamic;
13198         dp_model_t *model;
13199         const msurface_t *surface;
13200         const msurface_t *surfaces;
13201         const int *surfacelist;
13202         const texture_t *texture;
13203         int numtriangles;
13204         int numsurfacelist;
13205         int surfacelistindex;
13206         int surfaceindex;
13207         int triangleindex;
13208         float localorigin[3];
13209         float localnormal[3];
13210         float localmins[3];
13211         float localmaxs[3];
13212         float localsize;
13213         //float normal[3];
13214         float planes[6][4];
13215         float angles[3];
13216         bih_t *bih;
13217         int bih_triangles_count;
13218         int bih_triangles[256];
13219         int bih_surfaces[256];
13220
13221         decalsystem = &ent->decalsystem;
13222         model = ent->model;
13223         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13224         {
13225                 R_DecalSystem_Reset(&ent->decalsystem);
13226                 return;
13227         }
13228
13229         if (!model->brush.data_leafs && !cl_decals_models.integer)
13230         {
13231                 if (decalsystem->model)
13232                         R_DecalSystem_Reset(decalsystem);
13233                 return;
13234         }
13235
13236         if (decalsystem->model != model)
13237                 R_DecalSystem_Reset(decalsystem);
13238         decalsystem->model = model;
13239
13240         RSurf_ActiveModelEntity(ent, false, false, false);
13241
13242         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13243         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13244         VectorNormalize(localnormal);
13245         localsize = worldsize*rsurface.inversematrixscale;
13246         localmins[0] = localorigin[0] - localsize;
13247         localmins[1] = localorigin[1] - localsize;
13248         localmins[2] = localorigin[2] - localsize;
13249         localmaxs[0] = localorigin[0] + localsize;
13250         localmaxs[1] = localorigin[1] + localsize;
13251         localmaxs[2] = localorigin[2] + localsize;
13252
13253         //VectorCopy(localnormal, planes[4]);
13254         //VectorVectors(planes[4], planes[2], planes[0]);
13255         AnglesFromVectors(angles, localnormal, NULL, false);
13256         AngleVectors(angles, planes[0], planes[2], planes[4]);
13257         VectorNegate(planes[0], planes[1]);
13258         VectorNegate(planes[2], planes[3]);
13259         VectorNegate(planes[4], planes[5]);
13260         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13261         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13262         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13263         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13264         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13265         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13266
13267 #if 1
13268 // works
13269 {
13270         matrix4x4_t forwardprojection;
13271         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13272         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13273 }
13274 #else
13275 // broken
13276 {
13277         float projectionvector[4][3];
13278         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13279         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13280         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13281         projectionvector[0][0] = planes[0][0] * ilocalsize;
13282         projectionvector[0][1] = planes[1][0] * ilocalsize;
13283         projectionvector[0][2] = planes[2][0] * ilocalsize;
13284         projectionvector[1][0] = planes[0][1] * ilocalsize;
13285         projectionvector[1][1] = planes[1][1] * ilocalsize;
13286         projectionvector[1][2] = planes[2][1] * ilocalsize;
13287         projectionvector[2][0] = planes[0][2] * ilocalsize;
13288         projectionvector[2][1] = planes[1][2] * ilocalsize;
13289         projectionvector[2][2] = planes[2][2] * ilocalsize;
13290         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13291         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13292         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13293         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13294 }
13295 #endif
13296
13297         dynamic = model->surfmesh.isanimated;
13298         numsurfacelist = model->nummodelsurfaces;
13299         surfacelist = model->sortedmodelsurfaces;
13300         surfaces = model->data_surfaces;
13301
13302         bih = NULL;
13303         bih_triangles_count = -1;
13304         if(!dynamic)
13305         {
13306                 if(model->render_bih.numleafs)
13307                         bih = &model->render_bih;
13308                 else if(model->collision_bih.numleafs)
13309                         bih = &model->collision_bih;
13310         }
13311         if(bih)
13312                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13313         if(bih_triangles_count == 0)
13314                 return;
13315         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13316                 return;
13317         if(bih_triangles_count > 0)
13318         {
13319                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13320                 {
13321                         surfaceindex = bih_surfaces[triangleindex];
13322                         surface = surfaces + surfaceindex;
13323                         texture = surface->texture;
13324                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13325                                 continue;
13326                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13327                                 continue;
13328                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13329                 }
13330         }
13331         else
13332         {
13333                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13334                 {
13335                         surfaceindex = surfacelist[surfacelistindex];
13336                         surface = surfaces + surfaceindex;
13337                         // check cull box first because it rejects more than any other check
13338                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13339                                 continue;
13340                         // skip transparent surfaces
13341                         texture = surface->texture;
13342                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13343                                 continue;
13344                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13345                                 continue;
13346                         numtriangles = surface->num_triangles;
13347                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13348                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13349                 }
13350         }
13351 }
13352
13353 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13354 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)
13355 {
13356         int renderentityindex;
13357         float worldmins[3];
13358         float worldmaxs[3];
13359         entity_render_t *ent;
13360
13361         if (!cl_decals_newsystem.integer)
13362                 return;
13363
13364         worldmins[0] = worldorigin[0] - worldsize;
13365         worldmins[1] = worldorigin[1] - worldsize;
13366         worldmins[2] = worldorigin[2] - worldsize;
13367         worldmaxs[0] = worldorigin[0] + worldsize;
13368         worldmaxs[1] = worldorigin[1] + worldsize;
13369         worldmaxs[2] = worldorigin[2] + worldsize;
13370
13371         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13372
13373         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13374         {
13375                 ent = r_refdef.scene.entities[renderentityindex];
13376                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13377                         continue;
13378
13379                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13380         }
13381 }
13382
13383 typedef struct r_decalsystem_splatqueue_s
13384 {
13385         vec3_t worldorigin;
13386         vec3_t worldnormal;
13387         float color[4];
13388         float tcrange[4];
13389         float worldsize;
13390         int decalsequence;
13391 }
13392 r_decalsystem_splatqueue_t;
13393
13394 int r_decalsystem_numqueued = 0;
13395 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13396
13397 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)
13398 {
13399         r_decalsystem_splatqueue_t *queue;
13400
13401         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13402                 return;
13403
13404         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13405         VectorCopy(worldorigin, queue->worldorigin);
13406         VectorCopy(worldnormal, queue->worldnormal);
13407         Vector4Set(queue->color, r, g, b, a);
13408         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13409         queue->worldsize = worldsize;
13410         queue->decalsequence = cl.decalsequence++;
13411 }
13412
13413 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13414 {
13415         int i;
13416         r_decalsystem_splatqueue_t *queue;
13417
13418         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13419                 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);
13420         r_decalsystem_numqueued = 0;
13421 }
13422
13423 extern cvar_t cl_decals_max;
13424 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13425 {
13426         int i;
13427         decalsystem_t *decalsystem = &ent->decalsystem;
13428         int numdecals;
13429         int killsequence;
13430         tridecal_t *decal;
13431         float frametime;
13432         float lifetime;
13433
13434         if (!decalsystem->numdecals)
13435                 return;
13436
13437         if (r_showsurfaces.integer)
13438                 return;
13439
13440         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13441         {
13442                 R_DecalSystem_Reset(decalsystem);
13443                 return;
13444         }
13445
13446         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13447         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13448
13449         if (decalsystem->lastupdatetime)
13450                 frametime = (cl.time - decalsystem->lastupdatetime);
13451         else
13452                 frametime = 0;
13453         decalsystem->lastupdatetime = cl.time;
13454         decal = decalsystem->decals;
13455         numdecals = decalsystem->numdecals;
13456
13457         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13458         {
13459                 if (decal->color4ub[0][3])
13460                 {
13461                         decal->lived += frametime;
13462                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13463                         {
13464                                 memset(decal, 0, sizeof(*decal));
13465                                 if (decalsystem->freedecal > i)
13466                                         decalsystem->freedecal = i;
13467                         }
13468                 }
13469         }
13470         decal = decalsystem->decals;
13471         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13472                 numdecals--;
13473
13474         // collapse the array by shuffling the tail decals into the gaps
13475         for (;;)
13476         {
13477                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13478                         decalsystem->freedecal++;
13479                 if (decalsystem->freedecal == numdecals)
13480                         break;
13481                 decal[decalsystem->freedecal] = decal[--numdecals];
13482         }
13483
13484         decalsystem->numdecals = numdecals;
13485
13486         if (numdecals <= 0)
13487         {
13488                 // if there are no decals left, reset decalsystem
13489                 R_DecalSystem_Reset(decalsystem);
13490         }
13491 }
13492
13493 extern skinframe_t *decalskinframe;
13494 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13495 {
13496         int i;
13497         decalsystem_t *decalsystem = &ent->decalsystem;
13498         int numdecals;
13499         tridecal_t *decal;
13500         float faderate;
13501         float alpha;
13502         float *v3f;
13503         float *c4f;
13504         float *t2f;
13505         const int *e;
13506         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13507         int numtris = 0;
13508
13509         numdecals = decalsystem->numdecals;
13510         if (!numdecals)
13511                 return;
13512
13513         if (r_showsurfaces.integer)
13514                 return;
13515
13516         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13517         {
13518                 R_DecalSystem_Reset(decalsystem);
13519                 return;
13520         }
13521
13522         // if the model is static it doesn't matter what value we give for
13523         // wantnormals and wanttangents, so this logic uses only rules applicable
13524         // to a model, knowing that they are meaningless otherwise
13525         if (ent == r_refdef.scene.worldentity)
13526                 RSurf_ActiveWorldEntity();
13527         else
13528                 RSurf_ActiveModelEntity(ent, false, false, false);
13529
13530         decalsystem->lastupdatetime = cl.time;
13531         decal = decalsystem->decals;
13532
13533         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13534
13535         // update vertex positions for animated models
13536         v3f = decalsystem->vertex3f;
13537         c4f = decalsystem->color4f;
13538         t2f = decalsystem->texcoord2f;
13539         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13540         {
13541                 if (!decal->color4ub[0][3])
13542                         continue;
13543
13544                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13545                         continue;
13546
13547                 // update color values for fading decals
13548                 if (decal->lived >= cl_decals_time.value)
13549                 {
13550                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13551                         alpha *= (1.0f/255.0f);
13552                 }
13553                 else
13554                         alpha = 1.0f/255.0f;
13555
13556                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13557                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13558                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13559                 c4f[ 3] = 1;
13560                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13561                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13562                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13563                 c4f[ 7] = 1;
13564                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13565                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13566                 c4f[10] = decal->color4ub[2][2] * alpha;
13567                 c4f[11] = 1;
13568
13569                 t2f[0] = decal->texcoord2f[0][0];
13570                 t2f[1] = decal->texcoord2f[0][1];
13571                 t2f[2] = decal->texcoord2f[1][0];
13572                 t2f[3] = decal->texcoord2f[1][1];
13573                 t2f[4] = decal->texcoord2f[2][0];
13574                 t2f[5] = decal->texcoord2f[2][1];
13575
13576                 // update vertex positions for animated models
13577                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13578                 {
13579                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13580                         VectorCopy(rsurface.modelvertexposition[e[0]].vertex3f, v3f);
13581                         VectorCopy(rsurface.modelvertexposition[e[1]].vertex3f, v3f + 3);
13582                         VectorCopy(rsurface.modelvertexposition[e[2]].vertex3f, v3f + 6);
13583                 }
13584                 else
13585                 {
13586                         VectorCopy(decal->vertex3f[0], v3f);
13587                         VectorCopy(decal->vertex3f[1], v3f + 3);
13588                         VectorCopy(decal->vertex3f[2], v3f + 6);
13589                 }
13590
13591                 if (r_refdef.fogenabled)
13592                 {
13593                         alpha = RSurf_FogVertex(v3f);
13594                         VectorScale(c4f, alpha, c4f);
13595                         alpha = RSurf_FogVertex(v3f + 3);
13596                         VectorScale(c4f + 4, alpha, c4f + 4);
13597                         alpha = RSurf_FogVertex(v3f + 6);
13598                         VectorScale(c4f + 8, alpha, c4f + 8);
13599                 }
13600
13601                 v3f += 9;
13602                 c4f += 12;
13603                 t2f += 6;
13604                 numtris++;
13605         }
13606
13607         if (numtris > 0)
13608         {
13609                 r_refdef.stats.drawndecals += numtris;
13610
13611                 // now render the decals all at once
13612                 // (this assumes they all use one particle font texture!)
13613                 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);
13614                 R_Mesh_ResetTextureState();
13615                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13616                 GL_DepthMask(false);
13617                 GL_DepthRange(0, 1);
13618                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13619                 GL_DepthTest(true);
13620                 GL_CullFace(GL_NONE);
13621                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13622                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13623                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13624         }
13625 }
13626
13627 static void R_DrawModelDecals(void)
13628 {
13629         int i, numdecals;
13630
13631         // fade faster when there are too many decals
13632         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13633         for (i = 0;i < r_refdef.scene.numentities;i++)
13634                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13635
13636         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13637         for (i = 0;i < r_refdef.scene.numentities;i++)
13638                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13639                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13640
13641         R_DecalSystem_ApplySplatEntitiesQueue();
13642
13643         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13644         for (i = 0;i < r_refdef.scene.numentities;i++)
13645                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13646
13647         r_refdef.stats.totaldecals += numdecals;
13648
13649         if (r_showsurfaces.integer)
13650                 return;
13651
13652         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13653
13654         for (i = 0;i < r_refdef.scene.numentities;i++)
13655         {
13656                 if (!r_refdef.viewcache.entityvisible[i])
13657                         continue;
13658                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13659                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13660         }
13661 }
13662
13663 extern cvar_t mod_collision_bih;
13664 void R_DrawDebugModel(void)
13665 {
13666         entity_render_t *ent = rsurface.entity;
13667         int i, j, k, l, flagsmask;
13668         const msurface_t *surface;
13669         dp_model_t *model = ent->model;
13670         vec3_t v;
13671
13672         switch(vid.renderpath)
13673         {
13674         case RENDERPATH_GL11:
13675         case RENDERPATH_GL13:
13676         case RENDERPATH_GL20:
13677         case RENDERPATH_CGGL:
13678                 break;
13679         case RENDERPATH_D3D9:
13680                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13681                 return;
13682         case RENDERPATH_D3D10:
13683                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13684                 return;
13685         case RENDERPATH_D3D11:
13686                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13687                 return;
13688         }
13689
13690         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13691
13692         R_Mesh_ResetTextureState();
13693         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13694         GL_DepthRange(0, 1);
13695         GL_DepthTest(!r_showdisabledepthtest.integer);
13696         GL_DepthMask(false);
13697         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13698
13699         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13700         {
13701                 int triangleindex;
13702                 int bihleafindex;
13703                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13704                 const q3mbrush_t *brush;
13705                 const bih_t *bih = &model->collision_bih;
13706                 const bih_leaf_t *bihleaf;
13707                 float vertex3f[3][3];
13708                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13709                 cullbox = false;
13710                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13711                 {
13712                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13713                                 continue;
13714                         switch (bihleaf->type)
13715                         {
13716                         case BIH_BRUSH:
13717                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13718                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13719                                 {
13720                                         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);
13721                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13722                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13723                                 }
13724                                 break;
13725                         case BIH_COLLISIONTRIANGLE:
13726                                 triangleindex = bihleaf->itemindex;
13727                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13728                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13729                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13730                                 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);
13731                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13732                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13733                                 break;
13734                         case BIH_RENDERTRIANGLE:
13735                                 triangleindex = bihleaf->itemindex;
13736                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13737                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13738                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13739                                 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);
13740                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13741                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13742                                 break;
13743                         }
13744                 }
13745         }
13746
13747         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13748
13749         if (r_showtris.integer || r_shownormals.integer)
13750         {
13751                 if (r_showdisabledepthtest.integer)
13752                 {
13753                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13754                         GL_DepthMask(false);
13755                 }
13756                 else
13757                 {
13758                         GL_BlendFunc(GL_ONE, GL_ZERO);
13759                         GL_DepthMask(true);
13760                 }
13761                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13762                 {
13763                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13764                                 continue;
13765                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13766                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13767                         {
13768                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13769                                 if (r_showtris.value > 0)
13770                                 {
13771                                         if (!rsurface.texture->currentlayers->depthmask)
13772                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13773                                         else if (ent == r_refdef.scene.worldentity)
13774                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13775                                         else
13776                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13777                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13778                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13779                                         RSurf_DrawBatch();
13780                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13781                                         CHECKGLERROR
13782                                 }
13783                                 if (r_shownormals.value < 0)
13784                                 {
13785                                         qglBegin(GL_LINES);
13786                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13787                                         {
13788                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13789                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13790                                                 qglVertex3f(v[0], v[1], v[2]);
13791                                                 VectorMA(v, -r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13792                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13793                                                 qglVertex3f(v[0], v[1], v[2]);
13794                                         }
13795                                         qglEnd();
13796                                         CHECKGLERROR
13797                                 }
13798                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13799                                 {
13800                                         qglBegin(GL_LINES);
13801                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13802                                         {
13803                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13804                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13805                                                 qglVertex3f(v[0], v[1], v[2]);
13806                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13807                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13808                                                 qglVertex3f(v[0], v[1], v[2]);
13809                                         }
13810                                         qglEnd();
13811                                         CHECKGLERROR
13812                                         qglBegin(GL_LINES);
13813                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13814                                         {
13815                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13816                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13817                                                 qglVertex3f(v[0], v[1], v[2]);
13818                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13819                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13820                                                 qglVertex3f(v[0], v[1], v[2]);
13821                                         }
13822                                         qglEnd();
13823                                         CHECKGLERROR
13824                                         qglBegin(GL_LINES);
13825                                         for (k = 0, l = surface->num_firstvertex;k < surface->num_vertices;k++, l++)
13826                                         {
13827                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13828                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13829                                                 qglVertex3f(v[0], v[1], v[2]);
13830                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13831                                                 GL_Color(r_refdef.view.colorscale, 1, 1, 1);
13832                                                 qglVertex3f(v[0], v[1], v[2]);
13833                                         }
13834                                         qglEnd();
13835                                         CHECKGLERROR
13836                                 }
13837                         }
13838                 }
13839                 rsurface.texture = NULL;
13840         }
13841 }
13842
13843 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13844 int r_maxsurfacelist = 0;
13845 const msurface_t **r_surfacelist = NULL;
13846 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13847 {
13848         int i, j, endj, flagsmask;
13849         dp_model_t *model = r_refdef.scene.worldmodel;
13850         msurface_t *surfaces;
13851         unsigned char *update;
13852         int numsurfacelist = 0;
13853         if (model == NULL)
13854                 return;
13855
13856         if (r_maxsurfacelist < model->num_surfaces)
13857         {
13858                 r_maxsurfacelist = model->num_surfaces;
13859                 if (r_surfacelist)
13860                         Mem_Free((msurface_t**)r_surfacelist);
13861                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13862         }
13863
13864         RSurf_ActiveWorldEntity();
13865
13866         surfaces = model->data_surfaces;
13867         update = model->brushq1.lightmapupdateflags;
13868
13869         // update light styles on this submodel
13870         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13871         {
13872                 model_brush_lightstyleinfo_t *style;
13873                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13874                 {
13875                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13876                         {
13877                                 int *list = style->surfacelist;
13878                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13879                                 for (j = 0;j < style->numsurfaces;j++)
13880                                         update[list[j]] = true;
13881                         }
13882                 }
13883         }
13884
13885         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13886
13887         if (debug)
13888         {
13889                 R_DrawDebugModel();
13890                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13891                 return;
13892         }
13893
13894         rsurface.lightmaptexture = NULL;
13895         rsurface.deluxemaptexture = NULL;
13896         rsurface.uselightmaptexture = false;
13897         rsurface.texture = NULL;
13898         rsurface.rtlight = NULL;
13899         numsurfacelist = 0;
13900         // add visible surfaces to draw list
13901         for (i = 0;i < model->nummodelsurfaces;i++)
13902         {
13903                 j = model->sortedmodelsurfaces[i];
13904                 if (r_refdef.viewcache.world_surfacevisible[j])
13905                         r_surfacelist[numsurfacelist++] = surfaces + j;
13906         }
13907         // update lightmaps if needed
13908         if (model->brushq1.firstrender)
13909         {
13910                 model->brushq1.firstrender = false;
13911                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13912                         if (update[j])
13913                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13914         }
13915         else if (update)
13916         {
13917                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13918                         if (r_refdef.viewcache.world_surfacevisible[j])
13919                                 if (update[j])
13920                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13921         }
13922         // don't do anything if there were no surfaces
13923         if (!numsurfacelist)
13924         {
13925                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13926                 return;
13927         }
13928         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13929         GL_AlphaTest(false);
13930
13931         // add to stats if desired
13932         if (r_speeds.integer && !skysurfaces && !depthonly)
13933         {
13934                 r_refdef.stats.world_surfaces += numsurfacelist;
13935                 for (j = 0;j < numsurfacelist;j++)
13936                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13937         }
13938
13939         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13940 }
13941
13942 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13943 {
13944         int i, j, endj, flagsmask;
13945         dp_model_t *model = ent->model;
13946         msurface_t *surfaces;
13947         unsigned char *update;
13948         int numsurfacelist = 0;
13949         if (model == NULL)
13950                 return;
13951
13952         if (r_maxsurfacelist < model->num_surfaces)
13953         {
13954                 r_maxsurfacelist = model->num_surfaces;
13955                 if (r_surfacelist)
13956                         Mem_Free((msurface_t **)r_surfacelist);
13957                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13958         }
13959
13960         // if the model is static it doesn't matter what value we give for
13961         // wantnormals and wanttangents, so this logic uses only rules applicable
13962         // to a model, knowing that they are meaningless otherwise
13963         if (ent == r_refdef.scene.worldentity)
13964                 RSurf_ActiveWorldEntity();
13965         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13966                 RSurf_ActiveModelEntity(ent, false, false, false);
13967         else if (prepass)
13968                 RSurf_ActiveModelEntity(ent, true, true, true);
13969         else if (depthonly)
13970         {
13971                 switch (vid.renderpath)
13972                 {
13973                 case RENDERPATH_GL20:
13974                 case RENDERPATH_CGGL:
13975                 case RENDERPATH_D3D9:
13976                 case RENDERPATH_D3D10:
13977                 case RENDERPATH_D3D11:
13978                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13979                         break;
13980                 case RENDERPATH_GL13:
13981                 case RENDERPATH_GL11:
13982                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13983                         break;
13984                 }
13985         }
13986         else
13987         {
13988                 switch (vid.renderpath)
13989                 {
13990                 case RENDERPATH_GL20:
13991                 case RENDERPATH_CGGL:
13992                 case RENDERPATH_D3D9:
13993                 case RENDERPATH_D3D10:
13994                 case RENDERPATH_D3D11:
13995                         RSurf_ActiveModelEntity(ent, true, true, false);
13996                         break;
13997                 case RENDERPATH_GL13:
13998                 case RENDERPATH_GL11:
13999                         RSurf_ActiveModelEntity(ent, true, false, false);
14000                         break;
14001                 }
14002         }
14003
14004         surfaces = model->data_surfaces;
14005         update = model->brushq1.lightmapupdateflags;
14006
14007         // update light styles
14008         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14009         {
14010                 model_brush_lightstyleinfo_t *style;
14011                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14012                 {
14013                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14014                         {
14015                                 int *list = style->surfacelist;
14016                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14017                                 for (j = 0;j < style->numsurfaces;j++)
14018                                         update[list[j]] = true;
14019                         }
14020                 }
14021         }
14022
14023         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14024
14025         if (debug)
14026         {
14027                 R_DrawDebugModel();
14028                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14029                 return;
14030         }
14031
14032         rsurface.lightmaptexture = NULL;
14033         rsurface.deluxemaptexture = NULL;
14034         rsurface.uselightmaptexture = false;
14035         rsurface.texture = NULL;
14036         rsurface.rtlight = NULL;
14037         numsurfacelist = 0;
14038         // add visible surfaces to draw list
14039         for (i = 0;i < model->nummodelsurfaces;i++)
14040                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14041         // don't do anything if there were no surfaces
14042         if (!numsurfacelist)
14043         {
14044                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14045                 return;
14046         }
14047         // update lightmaps if needed
14048         if (update)
14049         {
14050                 int updated = 0;
14051                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14052                 {
14053                         if (update[j])
14054                         {
14055                                 updated++;
14056                                 R_BuildLightMap(ent, surfaces + j);
14057                         }
14058                 }
14059         }
14060         if (update)
14061                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14062                         if (update[j])
14063                                 R_BuildLightMap(ent, surfaces + j);
14064         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14065         GL_AlphaTest(false);
14066
14067         // add to stats if desired
14068         if (r_speeds.integer && !skysurfaces && !depthonly)
14069         {
14070                 r_refdef.stats.entities_surfaces += numsurfacelist;
14071                 for (j = 0;j < numsurfacelist;j++)
14072                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14073         }
14074
14075         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14076 }
14077
14078 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14079 {
14080         static texture_t texture;
14081         static msurface_t surface;
14082         const msurface_t *surfacelist = &surface;
14083
14084         // fake enough texture and surface state to render this geometry
14085
14086         texture.update_lastrenderframe = -1; // regenerate this texture
14087         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14088         texture.currentskinframe = skinframe;
14089         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14090         texture.offsetmapping = OFFSETMAPPING_OFF;
14091         texture.offsetscale = 1;
14092         texture.specularscalemod = 1;
14093         texture.specularpowermod = 1;
14094
14095         surface.texture = &texture;
14096         surface.num_triangles = numtriangles;
14097         surface.num_firsttriangle = firsttriangle;
14098         surface.num_vertices = numvertices;
14099         surface.num_firstvertex = firstvertex;
14100
14101         // now render it
14102         rsurface.texture = R_GetCurrentTexture(surface.texture);
14103         rsurface.lightmaptexture = NULL;
14104         rsurface.deluxemaptexture = NULL;
14105         rsurface.uselightmaptexture = false;
14106         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14107 }
14108
14109 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)
14110 {
14111         static msurface_t surface;
14112         const msurface_t *surfacelist = &surface;
14113
14114         // fake enough texture and surface state to render this geometry
14115
14116         surface.texture = texture;
14117         surface.num_triangles = numtriangles;
14118         surface.num_firsttriangle = firsttriangle;
14119         surface.num_vertices = numvertices;
14120         surface.num_firstvertex = firstvertex;
14121
14122         // now render it
14123         rsurface.texture = R_GetCurrentTexture(surface.texture);
14124         rsurface.lightmaptexture = NULL;
14125         rsurface.deluxemaptexture = NULL;
14126         rsurface.uselightmaptexture = false;
14127         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14128 }